我們知道,
this對象是運行時基於函數的執行環境綁定的:在全局函數中,this等於window,而當函數被作為某個對象的方法調用時,this等於那個對象。《Javascript高級程序設計》
在下面的例子中,理解閉包中的this對象。
var name = "The Window"; var object = { name: "My object", getNameFunc: function() { return function() { return this.name; }; } } alert(object.getNameFunc()()); // "The Window"
為什么最后的結果是"The Window"而不是object里面的name"My object"呢?
首先,要理解函數作為函數調用和函數作為方法調用。
我們把最后的一句拆成兩個步驟執行:
var first = object.getNameFunc(); var second = first();
其中第一步,獲得的first為返回的匿名函數,此時的getNameFunc()作為object的方法調用,如果在getNameFunc()中使用this,此時的this指向的是object對象。
第二部,調用first函數,可以很清楚的發現,此時調用first函數,first函數沒有在對象中調用,因此是作為函數調用的,是在全局作用域下,因此first函數中的this指向的是window。
再看下面這句話:
為什么匿名函數沒有取得其包含作用域(外部作用域)的this對象呢?
每個函數被調用時,其活動對象都會自動取得兩個特殊變量:this和arguments。內部函數在搜索這兩個變量時,只會搜索到其活動對象為止,因此永遠不可能直接訪問外部函數中的這兩個變量。 《Javascript高級程序設計》
那么,如何獲得外部作用域中的this呢?
可以把外部作用域中的this保存在閉包可以訪問到的變量里。如下:
var name = "The Window"; var object = { name: "My object", getNameFunc: function() { var that = this; // 將getNameFunc()的this保存在that變量中 var age = 15; return function() { return that.name; }; } } alert(object.getNameFunc()()); // "My object"
其中,getNameFunc()執行時的活動對象有:that/age/匿名函數,在執行匿名函數時,同時引用了getNameFunc()中的活動對象,因此可以獲取that和age的值。但是由於是在全局環境中調用的匿名函數,因此匿名函數內部的this還是指向window。