1. 程式人生 > >對this關鍵字的深入探究

對this關鍵字的深入探究

樣式 src 因此 完全 記錄 優先 spa img col

  this無疑是javascript中特別復雜的機制了,最使我們困擾的就是this的指向,僅以本文對我所理解的this做一個總結和記錄。每一句話都是重點!文章參考《你不知道的javascript》。

  首先需要對this有一個大概的理解:每個函數的this都是在調用時被綁定的,完全取決於函數的調用位置。

綁定規則

  當我們找到函數的調用位置以後,需要判斷應用了哪條綁定規則,綁定規則分為四種:默認綁定,隱式綁定,顯式綁定,new綁定。

一,默認綁定

  這是最常用的函數調用類型:獨立函數調用。可以把這條規則看作是無法應用其他規則時的默認應用。

  如下,這裏的foo()是直接使用不帶任何修飾的函數引用進行調用的,因此只能使用默認綁定,無法應用其他規則。

function foo() {
    console.log(this.a);
}
var a = 2;
foo();    //2

  註意雖然this的綁定規則完全取決於調用位置,但是只有foo()運行在非嚴格模式下默認綁定才能綁定到全局對象。嚴格模式下與foo()的調用位置無關。如果使用嚴格模式,那麽全局對象將無法使用默認綁定,因此會綁定到undefined。

function foo() {
    "use strict";
    console.log(this.a);
}
var a = 2;
foo();

  報錯:

技術分享圖片

二,隱式綁定

  這條規則需要考慮的是調用位置是否有上下文對象

,或者說是否被某個對象擁有或包含。當函數引用有上下文對象時,隱式綁定規則會把函數調用中的this綁定到這個上下文對象像下面這個樣子,調用foo()時this被綁定到obj,因此this.a和obj.a是一樣的:

  對象屬性引用鏈中只有最後一層會影響調用位置。

function foo() {
    console.log(this.a);
};
var obj2 = {
    a: 32,
    foo: foo
}
var obj1 = {
    a: 2,
    obj2: obj2
};
obj1.obj2.foo();    //32

隱式丟失

  這也是最常見的this綁定問題了,被隱式綁定的函數會丟失綁定對象,也就是說會應用默認綁定,從而把this綁定到全局對象或者undefined上(取決於是否嚴格模式)。

  有以下幾種情況:

  1.雖然bar是obj.foo的引用,但是實際上它引用的是foo函數本身,此時的bar便是一個不帶任何修飾的函數調用,因此應用了默認樣式。

function foo() {
    console.log(this.a);
};
var obj = {
    a: 2,
    foo: foo
}
var bar = obj.foo;
var a = "global";
bar();    //global

  2.參數傳遞其實就是一種隱式賦值,因此我們傳入函數時也會被隱式賦值。

function foo() {
    console.log(this.a);
};
function doFoo(fn) {
    fn();
}
var obj = {
    a: 2,
    foo: foo
}
var a = "global";
doFoo(obj.foo);    //global

  3.參數傳入內置函數時也是一樣

function foo() {
    console.log(this.a);
};
var obj = {
    a: 2,
    foo: foo
}
var a = "global";
setTimeout(obj.foo, 100);    //global

三,顯式綁定

  如果不想在對象內部包含函數引用,而想在某個對象上強制調用函數,可以使用call()和apply()方法,它們的第一個參數時對象,會把這個對象綁定到this。稱之為顯式綁定

  強制把foo的this綁定到obj,無論之後如何調用bar,總是會在obj上調用。

function foo() {
    console.log(this.a);
};
var obj = {
    a: 2
}
var bar = function() {
    foo.call(obj);
}
bar();    //2
setTimeout(bar, 100);    //2
bar.call(window);    //2  

四,new綁定

  使用new來調用foo時,會構造一個新的對象並把它綁定到foo()調用中的this上。

function foo(a) {
    this.a = a;
};
var bar = new foo(2);
console.log(bar.a);    //2

五,優先級

  既然幾種綁定規則討論完了,那麽我們來比較一下他們的優先級順序。細節不做討論,可以自行測試。總之結果是:new綁定 > 顯式綁定 > 隱式綁定 > 默認綁定

未完待續

對this關鍵字的深入探究