JavaScript開發中this給程式設計師挖的坑,你遇到過嗎?

對於程序員來說,this這個關鍵字應該是再熟悉不過了,在C++、C#以及Java中,它的身影隨處可見,this也可以說是編程語言JavaScript的精髓,但是一定也有不少JavaScript開發者都遇到過this的陷阱。

在C++、C#、Java中,this擁有十分明確的含義,就是單純指向當前的對象實例,但是,在動態編程語言JavaScript中,相同的this寫法,卻有不同的含義。

JavaScript開發中this給程序員挖的坑,你遇到過嗎?

JavaScript中的this代表函數運行時自動生成的一個內部對象,只能在函數內部使用。並且,你不能在創建統計this的時候就確定它,而應該在函數執行時進行確定,所以,一不留神,你就會掉進意想不到的坑!

0、誰調用了就誰來負責

我們先來看看代碼:

var name = 'a';

var obj = {

name: 'b',

getName: function() {

console.log(this.name);

}

};

obj.getName(); // b

var getName = obj.getName;

getName(); // a

var obj2 = (function() {

return function() {

console.log(this.name);

}

})();

obj2(); // a

首先,obj.getName()打印出來b,因為,obj調用了getName(),所以其this指向obj,this.name就是b。

其次,getName()打印出a的原因:理由是此時的obj並不調用getName(),而是全局變量window,因此,結果是a

最後,obj2中,因為採用了立即執行函數,它返回一個函數,而當我們調用時,調用它的也是全局變量window,所以打印結果也是a。

需要注意的是,匿名函數內的this是指向window的,更準確的說是指向調用者。

JavaScript開發中this給程序員挖的坑,你遇到過嗎?

1、必須瞭解new的過程

function Test() {

console.log(this.name);

}

Test(); // a

var test = new Test(); // undefined

function Test2() {

this.name = 'c';

}

var test2 = new Test2();

console.log(test2.name); // c

為什麼這個例子最終打印出來的是c呢?這裡new的過程不可忽略,new Test2() 其實執行了三步動作:

首先,創建一個空對象obj(var obj = {};),然後,將這個空對象的[[Prototype]](__proto__)成員指向了Test2函數對象prototype成員對象最後,將Test2函數對象的this指針替換成obj:

obj.__proto__ = Test2.prototype;

Test2.call(obj);

當沒有顯式返回值或者返回為基本類型、null時,默認將 this 返回(參考2)

因此,在這個例子中,當你使用new的時候,函數內部的this指向已經改變了,不再指向window。

主要應該搞清楚new的過程,然後就知道打印出c的原因了。

JavaScript開發中this給程序員挖的坑,你遇到過嗎?

2、奇怪的return

看過上面的例子後,你是否覺得已經掌握了new的函數內的this指向?千萬別掉以輕心,在JavaScript中,多的是例外,如:

function Test3() {

this.name = 'd';

return {};

}

var test3 = new Test3();

console.log(test3.name); // undefined

function Test4() {

this.name = 'd';

return 1;

}

var test4 = new Test4();

console.log(test4.name); // d

可以再試試return 'd' | null | undefined中的一個或更多類型。

結論:如果return的是一個對象(null除外),那麼this指向的這個對象,否則this依舊指向實例對象。


分享到:


相關文章: