老生常談的問題了衣摩,之前一直有些模糊昂验,這次爭取一次寫清楚。
指向只與調(diào)用有關(guān)
不論代碼多么復(fù)雜我們只關(guān)心到底是誰最后調(diào)用的this就可以了。
- 來看一個例子:
var obj = {
foo: function(){
console.log(this)
}
}
var bar = obj.foo
obj.foo() // obj
bar() // window
為什么最后兩行所打印出的this不同既琴?還是那句話 “誰最后調(diào)用的this占婉,this就指向誰∏喊穑”
- 先看第一行調(diào)用foo()函數(shù)的對象是obj锐涯,所以this指向obj。
- 前面沒有調(diào)用的對象那么就是全局對象 window填物,所以調(diào)用bar()函數(shù)的對象是全局window纹腌,相當(dāng)于window.bar(),所以this指向window(嚴(yán)格模式下全局為undifined)
改變this指向的方法
箭頭函數(shù)下的this
箭頭函數(shù)下的this有些特殊滞磺,函數(shù)體內(nèi)的this對象就是定義時的所在的對象升薯,而不是使用時所在的對象。
- 例子
function Timer(){
this.s1 = 0
this.s2 = 0
setInterval(()=> this.s1++,1000)
setInterval(function(){
this.s2 ++
},1000)
}
let timer = new Timer()
setTimeout(() => console.log(timer.s1),3100) // 3
setTimeout(() => console.log(timer.s2),3100) // 0
上面的例子击困,Timer函數(shù)內(nèi)部設(shè)置了兩個定時器涎劈,分別使用了箭頭函數(shù)和普通函數(shù),箭頭函數(shù)的this指向函數(shù)定義時所在的作用于(即Timer函數(shù))阅茶,普通函數(shù)的this指向調(diào)用時所在的作用于(即全局對象window)蛛枚。所以,3100ms之后脸哀,timer.s1加到了3蹦浦,而timer.s2一次都沒有更新。
apply & call
apply call bind 都可以改變this的指向撞蜂,這里先說apply 和 call 的區(qū)別盲镶。
apply 和 call 的區(qū)別是 call 方法接受的是若干個參數(shù)列表,而 apply 接收的是一個包含多個參數(shù)的數(shù)組蝌诡。
- apply
var a ={
fn : function (a,b) {
console.log( a + b)
}
}
var b = a.fn;
b.apply(a,[1,2]) // 3
- call
var a ={
fn : function (a,b) {
console.log( a + b)
}
}
var b = a.fn;
b.call(a,1,2) // 3
bind 和 call apply
直接看MDN上面的介紹:
bind()方法創(chuàng)建一個新的函數(shù), 當(dāng)被調(diào)用時溉贿,將其this關(guān)鍵字設(shè)置為提供的值,在調(diào)用新函數(shù)時浦旱,在任何提供之前提供一個給定的參數(shù)序列宇色。
var a ={
fn : function (a,b) {
console.log( a + b)
}
}
var b = a.fn;
b.bind(a,1,2)() // 3