JavaScript閉包和this綁定

本文最主要講講JavaScript閉包和this綁定相關的個人小發現,鑑於這方面的基礎知識已經有不少很好的文章講過了,因此基本的就不講了,推薦看看酷殼上的理解Javascript的閉包阮一峯學習Javascript閉包(Closure),寫的都很是好。javascript

首先來說講阮一峯的文章中的兩道思考題。html

代碼片斷一java

var name = "The Window";
var object = {
    name : "My Object",
    getNameFunc : function(){
        return function(){
            return this.name;
        };
    }
};
alert(object.getNameFunc()());

這段代碼最後輸出的是shell

The Window

緣由在同一片文章的評論中已經有人指出了數據結構

George Wing 說:閉包

上面本人說得不太正確。
this的指向是由它所在函數調用的上下文決定的,而不是由它所在函數定義的上下文決定的。函數

對於最後返回的這個匿名函數學習

function(){
    return this.name;
};

它是做爲一個獨立的函數返回的,它的調用域是在全局上,因此會輸出全局變量name。this

代碼片斷二spa

var name = "The Window";
var object = {
    name : "My Object",
    getNameFunc : function(){
        var that = this;
        return function(){
            return that.name;
        };
    }
};
alert(object.getNameFunc()());

代碼片斷二最後輸出的是

My Object

這裏就要考慮var that = this;這句的做用了,因爲getNameFuncobject內部的函數,因此它調用的上下文this保存的是object的信息,將其保存到that變量,這樣做爲內部函數的匿名函數就能夠直接訪問了。

能夠注意到的是,阮一峯文章中的代碼,都是將經過一個JSON對象來訪問內部的函數,這樣其實有些地方還不夠清晰,畢竟不怎麼嚴格地說,閉包就是函數內部的函數,因此我借用CoolShell上的文章中的例子來進一步說明。

代碼片斷三

function greeting(name) {
    var text = 'Hello ' + name; // local variable
    // 每次調用時,產生閉包,並返回內部函數對象給調用者
    return function() { alert(text); }
}
var sayHello=greeting("Closure");
sayHello()  // 經過閉包訪問到了局部變量text

這段代碼輸出

Hello Closure

看上去好像很好理解,接下來看代碼片斷四:

代碼片斷四

var text = 'findingsea';
function greeting(name) {
    var text = 'Hello ' + name; // local variable
    // 每次調用時,產生閉包,並返回內部函數對象給調用者
    return function() { alert(this.text); }
}
var sayHello=greeting("Closure");
sayHello()  // 經過閉包訪問到了局部變量text

這段代碼輸出

findingsea

這是爲何呢?

針對代碼片斷三,CoolShell上的原文有解釋:

文法環境中用於解析函數執行過程使用到的變量標識符。咱們能夠將文法環境想象成一個對象,該對象包含了兩個重要組件,環境記錄(Enviroment Recode),和外部引用(指針)。環境記錄包含包含了函數內部聲明的局部變量和參數變量,外部引用指向了外部函數對象的上下文執行場景。全局的上下文場景中此引用值爲NULL。這樣的數據結構就構成了一個單向的鏈表,每一個引用都指向外層的上下文場景。

closure

針對代碼片斷四,就是咱們以前講過的,this保存是調用環境下的上下文內容,因此會輸出全局的text

總結

本文想說明的是如下兩點:

  1. 在函數閉包中,不使用this對變量進行訪問時,函數會經過文法環境中的外部引用(指針),一級級地往上找(單向鏈表),直到找到(或者最終找不到)對應的變量。這個結構是在函數定義的時候就決定了的。
  2. 在函數閉包中,使用this對變量進行訪問時,和絕大多數語言不一樣,JavaScript的this保存的是調用環境的上下文,也就是說this中的內容是在調用的時候決定的,因此訪問到的是當前環境下的對應變量,並不會像前一種狀況同樣進行逐級查找。
相關文章
相關標籤/搜索