判斷this指向
對于普通的function函數(shù)來說备畦,this的行為與動態(tài)作用域很相似武通,而箭頭函數(shù)的this的行為則更像詞法作用域堪滨。所謂動態(tài)作用域畔勤,簡單來講就是在運行時才能夠確定的作用域蕾各,與之相對的是詞法作用域,就是在書寫代碼的階段確定的作用域硼被。
由于this是在函數(shù)被調(diào)用時才能判斷其指向的,因此this指向的判斷一直是令很多新手頭疼的點渗磅。其實判斷this指向并不難嚷硫,只要遵循以下步驟即可(優(yōu)先級由高到低):
是否由new調(diào)用,若有則指向新創(chuàng)建的對象本身
有無call始鱼、apply仔掸、bind的顯式綁定,若有則指向指定的對象
隱式調(diào)用医清,指向調(diào)用函數(shù)的那個上下文對象
以上皆無起暮,在非嚴格模式下綁定到全局對象(window或global),嚴格模式下綁定到undefined
手動實現(xiàn)call()
call()和bind()都是改變函數(shù)this指向的方法会烙,不同之處在與call()是立即調(diào)用而bind()是返回一個函數(shù)的副本
思路:對于
o1.hi.myCall(o2)
將o1中的hi()添加到o2中负懦,再調(diào)用o2剛剛添加的hi()筒捺,此時已經(jīng)得到了結(jié)果,接著刪除o2的hi()纸厉,返回結(jié)果即可系吭。
Function.prototype.myCall = function (context, ...args) {
let temp = Symbol('call');
context = context || window;
context[temp] = this;
let result = context[temp](...args);
delete context[temp];
return result;
}
測試一下結(jié)果
let o1 = {
a: 11,
hi(b, c) {
console.log(this.a, b, c);
}
};
let o2 = {
a: 22
};
//test
let foo = o1.hi.myBind(o2, 8, 9);
foo();//22 8 9
手動實現(xiàn)bind()
由于上面已經(jīng)實現(xiàn)了call()祝辣,直接調(diào)用即可
Function.prototype.myBind = function (context, ...args) {
if (typeof this !== 'function') {
throw new TypeError('myBind callback is not a function');
}
return () => {
return this.myCall(context, ...args);
}
}
測試一下結(jié)果
//test
let foo = o1.hi.myBind(o2, 8, 9);
foo();//22 8 9