JS基礎——call、bind、apply 和 this

this

首先我們分析一下下面代碼的執行結果

function foo(num) {
     console.log( "foo: " + num );
     this.count++;  //記錄函數執行次數
}
foo.count = 0;
function test(){
    for(let i = 0 ; i < 4; i++){
        foo(i)
    }
    console.log('foo執行次數:'+foo.count)
}
test()

執行結果如下:

foo: 0
foo: 1
foo: 2
foo: 3
foo執行次數:0

由此可見this指向的並不是函數自身。this 是在運行時進行綁定的,它的指向取決於它的調用位置。我們可以通過分析調用棧來找到函數的調用位置。(調用位置爲當前正在執行的函數的前一個調用中)。當我們在第一個例子中增加debugger,在瀏覽器工具中可以清晰的看到函數的調用棧:
clipboard.png
foo函數的調用位置在test函數中,此時this的指向默認綁定爲window,而不是foo對象。我們可以可以通過修改this.countfoo.count來達到目的。

綁定

this的綁定規則有:默認綁定、隱式綁定、顯式綁定、new綁定,上面函數調用中this就是默認綁定。

new綁定

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

當使用new調用foo函數時,會構造一個新對象並把它綁定到 foo

顯式綁定

我們可以通過call、bind、apply來改變this的指向。call、apply本質上沒有區別,都是立即執行,只是第二個參數的傳值方式不一樣。bind返回要執行的函數,需要的時候再執行。(bind後的函數當使用new執行時,綁定無效)

function foo() { 
     console.log(this.a);
}
var obj = { 
     a:2
};
var fn = foo.bind( obj );
fn()   //2
new fn()  //undefined

隱式綁定

當函數存在上下文對象時會影響調用位置

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

箭頭函數

箭頭函數會繼承外層函數調用的 this 綁定

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章