(1)全局環境 在全局環境使用this,它指的就是頂層對象window。 (2)構造函數 構造函數中的this,指的是實例對象。 (3)對象的方法 當A對象的方法被賦予B對象,該方法中的this就從指向A對象變成了指向B對象。所以要特別小心,將某個對象的方法賦值給另一個對象,會改變this的指向。 ...
(1)全局環境
在全局環境使用this
,它指的就是頂層對象window
。
this === window // true
function f() {
console.log(this === window); // true
}
不管是不是在函數內部,只要是在全局環境下運行,this
就是指頂層對象window
。
(2)構造函數
構造函數中的this
,指的是實例對象。
var Obj = function (p) { this.p = p; }; Obj.prototype.m = function() { return this.p; };
上面代碼定義了一個構造函數Obj
。由於this
指向實例對象,所以在構造函數內部定義this.p
,就相當於定義實例對象有一個p
屬性;然後m
方法可以返回這個p屬性。
(3)對象的方法
當A對象的方法被賦予B對象,該方法中的this
就從指向A對象變成了指向B對象。所以要特別小心,將某個對象的方法賦值給另一個對象,會改變this
的指向。
var obj ={ foo: function () { console.log(this); } }; obj.foo() // obj
obj.foo
方法執行時,它內部的this
指向obj
。
但是,只有這一種用法(直接在obj
對象上調用foo
方法),this
指向obj
;其他用法時,this
都指向代碼塊當前所在對象(瀏覽器為window
對象)。
// 情況一
(obj.foo = obj.foo)() // window
// 情況二
(false || obj.foo)() // window
// 情況三
(1, obj.foo)() // window
obj.foo
先運算再執行,即使它的值根本沒有變化,this
也不再指向obj
了。
可以這樣理解,在JavaScript引擎內部,obj
和obj.foo
儲存在兩個記憶體地址,簡稱為M1
和M2
。只有obj.foo()
這樣調用時,是從M1
調用M2
,因此this
指向obj
。但是,上面三種情況,都是直接取出M2
進行運算,然後就在全局環境執行運算結果(還是M2
),因此this
指向全局環境。
// 情況一 (obj.foo = function () { console.log(this); })() // 情況二 (false || function () { console.log(this); })() // 情況三 (1, function () { console.log(this); })()
同樣的,如果某個方法位於多層對象的內部,這時為了簡化書寫,把該方法賦值給一個變數,往往會得到意料之外的結果。
var a = {
b: {
m: function() {
console.log(this.p);
},
p: 'Hello'
}
};
var hello = a.b.m;
hello() // undefined
上面代碼中,m
是多層對象內部的一個方法。為求簡便,將其賦值給hello
變數,結果調用時,this
指向了頂層對象。為了避免這個問題,可以只將m
所在的對象賦值給hello
,這樣調用時,this
的指向就不會變。
var hello = a.b; hello.m() // Hello
(4)Node
在Node中,this
的指向又分成兩種情況。全局環境中,this
指向全局對象global
;模塊環境中,this
指向module.exports。
// 全局環境 this === global // true // 模塊環境 this === module.exports // true
原文鏈接:
http://javascript.ruanyifeng.com/oop/this.html