成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

JavaScript學習之路 — 函數(shù)、閉包與原型鏈

klivitamJ / 1479人閱讀

摘要:全局的函數(shù)第個對象第個對象作為構(gòu)造器進行調(diào)用也就是利用運算符進行調(diào)用。與操作的共同使用只有通過操作產(chǎn)生的對象,可以使用構(gòu)造器函數(shù)原型鏈上的內(nèi)容,否則對象只能使用自己原型鏈上的內(nèi)容。

今天這個話題是因為這幾天看了《JavaScript忍者秘籍》,感覺這本書把這幾個內(nèi)容講的蠻透徹了,特撰本文,以便日后翻閱。(應該都會以知識點的形式給出吧。)

函數(shù) 1.【基本類型】

JavaScript中函數(shù)為first-class object,typeof的結(jié)果是object,沒有function這個基本類型,但有可以調(diào)用的Function構(gòu)造器。說到這個就列舉一下JavaScript中的幾個基本類型:

            * null                       (空值)
            * undefined           (未定義)
            * boolean              (布爾)
            * number              (數(shù)字)
            * string                  (字符串)
            * object                 (對象)
            * symbol               (符號)

除了null的typeof結(jié)果是object以外,其他類型的typeof都是自己的基本類型名稱。這幾個類型還能有一堆可以講的地方、之后再寫~

2.【函數(shù)聲明】

函數(shù)的字面量聲明有四個部分組成,但有些可以省略,列舉如下:

    * function 關(guān)鍵字
    * 可選名稱 ,可以匿名,但如果有必須為有效的JavaScript 標識符
    * 括號內(nèi)部一個以逗號分隔的參數(shù)列表
    * 大括號括起來的函數(shù)體
3.【name屬性】

有名稱的函數(shù)name屬性永遠為自己的名稱。關(guān)于匿名函數(shù)賦予變量后的name屬性是什么。。。我這里試出來ES5和ES6都是賦予后的變量名。

4.【函數(shù)調(diào)用與this的綁定】

在這本《忍者秘籍》里給出了一個理解this綁定的方法:將this理解為運行上下文,this指的就是調(diào)用函數(shù)時的運行上下文。this的綁定實在運行時候確定的,而不是編譯時。(在《你不知道的JavaScript》中詳細講了四種this綁定,以后補~)

這里講了四種函數(shù)調(diào)用的方式:

作為一個函數(shù)進行調(diào)用

就是作為一般的函數(shù),直接在全局上下文中調(diào)用。

作為一個方法進行調(diào)用
將函數(shù)作為一個對象中的方法進行調(diào)用,那么這時候this就會綁定在這個對象的上下文中。同時如果在全局中定義一個函數(shù),賦值到對象的屬性中,其可以對不同對象進行操作,互不影響。

//全局的函數(shù)
function all () {
    console.log(this.a);
}
//第1個對象
let o1 = {
    a: "In1",
    func1: function () {
        return this.a
    },
    func2: all
 }
//第2個對象
let o2 = {
    a: "In2",
    func: all
}

let a = "Out" 

console.log(o1.func1())   //method in object    In1
o1.func2()      //this is o1      In1
o2.func()       //this is o2      In2

作為構(gòu)造器進行調(diào)用

也就是利用new運算符進行調(diào)用。構(gòu)造器調(diào)用的時候會進行以下步驟:

      1.創(chuàng)建一個新的對象
      2.傳遞給構(gòu)造器的參數(shù)的對象是this參數(shù),從而成為構(gòu)造器的函數(shù)上下文
      3.如果沒有顯示的返回值,創(chuàng)建的對象則作為構(gòu)造器的返回值返回
      (即使有return值,作為3構(gòu)造器調(diào)用的時候,
      也返回新創(chuàng)建的對象,如果return的object,那就返回這個object)
    
    Ex:
function Ninja () {
    this.ninjaName = function () {}
    return 3
}

let ninja1 = new Ninja()
let ninja2 = new Ninja()

 //利用構(gòu)造器得到兩個不同的對象
console.log(ninja1 === ninja2)    //false
//作為構(gòu)造器調(diào)用時,返回的是對象而不是return值
console.log(ninja1)        // Ninja { ninjaName: [Function] }
//作為一般函數(shù)調(diào)用時,返回的是返回值
console.log(Ninja())      //3

通過apply()或call()方法進行調(diào)用

可以隨意改變函數(shù)的調(diào)用上下文,apply與call的區(qū)別是除第一個指定函數(shù)執(zhí)行時
this綁定參數(shù)之外的參數(shù)。apply傳入?yún)?shù)數(shù)組,而call傳入全部參數(shù)。

5.【函數(shù)參數(shù)】

函數(shù)實際傳入的參數(shù)和聲明時候的參數(shù)列表可以不同。
如果傳入的比聲明的少,那么沒有傳入數(shù)據(jù)的聲明將會是undefined,若多,則多出來的的傳入數(shù)據(jù)將無法通過變量名的方式訪問到。
參數(shù)可以通過函數(shù)的argument屬性訪問到,這是一個類數(shù)組,無法使用大多的數(shù)組的自帶方法。

6.【匿名函數(shù)】

對象內(nèi)的匿名函數(shù)如果被賦值給了另一個對象,會產(chǎn)生引用丟失的問題。

7.【函數(shù)的屬性】

函數(shù)作為對象,可以存儲一些參數(shù)值,以方便做一些特殊的處理。主要用途有函數(shù)存儲和自記憶函數(shù)。
函數(shù)存儲可以用來存儲要調(diào)用的函數(shù),自記憶函數(shù)可以用來緩存函數(shù)已經(jīng)運行過的結(jié)果,減少重復計算(自記憶函數(shù)可以通過閉包的方式進行再優(yōu)化)

8.【函數(shù)的變長參數(shù)】

可以通過apply方法給出變長參數(shù)的數(shù)組。(ES6中可以使用...解包)
如:

let list = [7,9,1,2,0,10]
Math.max(list[0],list[1]....) //此處省略,過于麻煩,要列出所有位置
Math.max.apply(Math, list)    //利用apply可以直接傳入數(shù)組
Math.max(...list)            //ES6中可以通過解包符直接傳入

通過閉包的特性,同樣可以實現(xiàn)通過參數(shù)個數(shù)不同的判斷,進行函數(shù)的重載。

閉包 1.【閉包的定義】

閉包是一個函數(shù)在創(chuàng)建時允許自身訪問并操作該函數(shù)之外的變量時所創(chuàng)建的作用域。->聲明的函數(shù)什么時候都可以調(diào)用,即使是在作用域消失之后。
典型的閉包:

let outer = "ninja"
let later

function outerFunction () {
    let inner = "samurai"
    
    function innerFunction (paramValue) {
        console.log(inner)
        console.log(paramValue)
        console.log(toolate)
    }

    later = innerFunction
}
    console.log(toolate)    //undefined (用let會報錯)
    var toolate = "ronin"
    outerFunction()   //創(chuàng)建閉包
    later("wakizashi")    //ninja wakizashi ronin 都輸出了

閉包創(chuàng)建了一個氣泡,保護了函數(shù)聲明那一時間點的作用域里的所有函數(shù)和變量,獲得了執(zhí)行操作所需要的所有東西。
有三個有趣的結(jié)論:

內(nèi)部函數(shù)的參數(shù)是包含在閉包中的

作用域之外的所有變量,即使是函數(shù)聲明之后,但是在函數(shù)被調(diào)用之前的那些聲明也都包含在閉包中

相同的作用域內(nèi),尚未聲明的變量不能使用(let聲明)、值為undefined(var聲明)

2.【閉包的用處】

創(chuàng)建私有變量:利用function的特性,可以創(chuàng)建一個變量無法在外部直接訪問,需要用getter和setter,這兩個函數(shù)就是閉包的作用

回調(diào)和計時器:回調(diào)函數(shù)中可以通過閉包來訪問外部的變量

3.【綁定函數(shù)上下文(bind)】bind函數(shù)的用法與apply和call不同,

簡化版的bind:

function bind (context, name) {
    return function () {
        return context[name].apply(context, arguments)
    }
}
//通過閉包的特性,來得到要綁定的函數(shù)
//系統(tǒng)bind的使用:
functionName.bind(newThis)()
4.【使用閉包實現(xiàn)的函數(shù)緩存記憶】

使用到的技巧:每個函數(shù)都有自己的上下文,所以函數(shù)從來都不是閉包的一部分。但是可以通過創(chuàng)建一個變量引用到這個上下文中(let fn = this,后面的function中可以利用fn調(diào)用到之前的this指向的上下文),從而將上下文也通過閉包保存起來。

具體的實現(xiàn)可以參見《忍者秘籍》書P103

5.【函數(shù)的即時調(diào)用】

通常用于匿名函數(shù),主要作用是可以保護作用域和變量名不污染全局。
并且可以解決迭代問題(同樣可以用來解決變量名稱過長的問題,將長名稱傳入即時調(diào)用的函數(shù)中,在函數(shù)中利用參數(shù)名進行操作):

for(let i = 0;i < div.length; i++) {
    (function(n) {
        div[n].addEventListener("click", function(){
            alert("div #" + n + "was clicked")
        }, false)
    })(i)
}
//通過立即執(zhí)行函數(shù),直接把i和對應的div綁定,如果不這樣做,最后按所有的按鈕都會是最后一個i值(因為沒有實時綁定)

閉包肯定不止這么多內(nèi)容,以后還會補充《你不知道的JavaScript》的內(nèi)容

原型鏈

JavaScript通過原型鏈實現(xiàn)繼承。

1.【prototype與new操作的共同使用】

只有通過new操作產(chǎn)生的對象,可以使用構(gòu)造器函數(shù)原型鏈上的內(nèi)容,否則對象只能使用自己原型鏈上的內(nèi)容。利用這個可以得出,利用構(gòu)造器函數(shù)可以將JavaScript產(chǎn)生類似于類的概念。

2.【prototype的使用】

prototype在對象創(chuàng)建之后如果有改動,所做的改動同樣會影響到已經(jīng)創(chuàng)建的對象上去。
對于對象中的引用,先檢查是否在自己的聲明中存在,如果存在則用自己聲明的,如果不存在則循著原型鏈向上找,找到object根元素,如果仍然不存在,則返回undefined。
prototype其實是object隱藏屬性constructor的一個屬性,所以可以利用這個進行原型鏈,原型是實時附加在對象上的。

3.【保持原型鏈】

用一個對象的實例作為另一個對象的原型,調(diào)用方式如下

SubClass.prototype = new SuperClass()

這樣SubClass的實例不僅擁有原型,更有SuperClass中的所有屬性。并且instanceOf SuperClass也會判斷正確。

注意: 永遠不要使用SubClass.prototype = SuperClass.prototype,如果這樣做的話所有SubClass上的prototype修改都會影響到SuperClass上,會產(chǎn)生副作用。

4.【hasOwnProperty()方法】

利用這個方法可以檢測屬性是否是原生就有的,而不是通過檢測原型鏈得到的。

5.【一些需要避免的場景】

擴展Object的prototype,這樣會影響到所有的對象

擴展Number的prototype

產(chǎn)生原生對象的子類(盡量采用另外寫類,但同名方法通過prototype來調(diào)用原生對象方法的方法)

通過構(gòu)造器創(chuàng)建對象不加new操作符(這樣做會有可能產(chǎn)生錯誤得不到對象并且污染全局變量)

這些就是讀完《忍者秘籍》的一部分感想和知識點,這本書最精華的部分應該就是這三塊的精煉描述了,這本書還講到了JavaScript的測試方法、正則表達式、定時器、運行時求值、事件與DOM操作以及一些跨瀏覽器的實踐方法。是一本好書(經(jīng)常參加促銷的好書~),可以借來或者買來一讀~。

以上。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/84809.html

相關(guān)文章

  • 2017-08-23 前端日報

    摘要:前端日報精選免費的計算機編程類中文書籍英文技術(shù)文檔看不懂看印記中文就夠了的內(nèi)部工作原理美團點評點餐前后端分離實踐讓你的動畫坐上時光機中文譯有多棒簡書譯別再使用圖片輪播了掘金譯如何在中使用掘金個讓增長成億美元公司的獨特方法眾成翻 2017-08-23 前端日報 精選 FPB 2.0:免費的計算機編程類中文書籍 2.0英文技術(shù)文檔看不懂?看印記中文就夠了!Virtual DOM 的內(nèi)部工作...

    lordharrd 評論0 收藏0
  • JS程序

    摘要:設(shè)計模式是以面向?qū)ο缶幊虨榛A(chǔ)的,的面向?qū)ο缶幊毯蛡鹘y(tǒng)的的面向?qū)ο缶幊逃行┎顒e,這讓我一開始接觸的時候感到十分痛苦,但是這只能靠自己慢慢積累慢慢思考。想繼續(xù)了解設(shè)計模式必須要先搞懂面向?qū)ο缶幊?,否則只會讓你自己更痛苦。 JavaScript 中的構(gòu)造函數(shù) 學習總結(jié)。知識只有分享才有存在的意義。 是時候替換你的 for 循環(huán)大法了~ 《小分享》JavaScript中數(shù)組的那些迭代方法~ ...

    melody_lql 評論0 收藏0
  • 我的前端進階之路

    摘要:事件模型事件捕獲階段。事件到達目標元素觸發(fā)目標元素的監(jiān)聽函數(shù)。的狀態(tài)值與狀態(tài)碼的狀態(tài)值未初始化還沒有調(diào)用方法。載入完成已經(jīng)執(zhí)行完成,已經(jīng)接收到全部的響應內(nèi)容。 前言 總括: 包含這三個月來碰到的一些覺得比較好的面試題,三個月沒怎么寫博客著實有些手癢,哈哈哈。7000余字,不成敬意2333 原文地址:我的前端進階之路 知乎專欄&&簡書專題:前端進擊者(知乎)&&前端進擊者(簡書) 博主...

    cloud 評論0 收藏0
  • 我的前端進階之路

    摘要:事件模型事件捕獲階段。事件到達目標元素觸發(fā)目標元素的監(jiān)聽函數(shù)。的狀態(tài)值與狀態(tài)碼的狀態(tài)值未初始化還沒有調(diào)用方法。載入完成已經(jīng)執(zhí)行完成,已經(jīng)接收到全部的響應內(nèi)容。 前言 總括: 包含這三個月來碰到的一些覺得比較好的面試題,三個月沒怎么寫博客著實有些手癢,哈哈哈。7000余字,不成敬意2333 原文地址:我的前端進階之路 知乎專欄&&簡書專題:前端進擊者(知乎)&&前端進擊者(簡書) 博主...

    zorpan 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<