我們都知道call apply bind都可以改變函數(shù)調(diào)用的this指向蹦骑。那么它們?nèi)哂惺裁磪^(qū)別慈省,什么時(shí)候該用哪個(gè)呢?
call眠菇、apply與bind的差別
call和apply改變了函數(shù)的this上下文后便執(zhí)行該函數(shù),而bind則是返回改變了上下文后的一個(gè)函數(shù)边败。
call、apply的區(qū)別
他們倆之間的差別在于參數(shù)的區(qū)別捎废,call和aplly的第一個(gè)參數(shù)都是要改變上下文的對(duì)象放闺,而call從第二個(gè)參數(shù)開(kāi)始以參數(shù)列表的形式展現(xiàn),apply則是把除了改變上下文對(duì)象的參數(shù)放在一個(gè)數(shù)組里面作為它的第二個(gè)參數(shù)缕坎。
封裝apply
Function.prototype.mApply = function (that, argu) {
that = that || window;
var n = this.name; // 函數(shù)名
// 修改函數(shù)名,以防與對(duì)象中其他屬性沖突
n += (Math.random() + '').slice(2, 12) + new Date() * 1;
// 將函數(shù)賦給對(duì)象
that[n] = this;
var res = that[n](...argu);
delete that[n];
return res;
}
封裝call
Function.prototype.mCall = function (that, ...argu) {
console.log(this); // 打印了調(diào)用mCall的函數(shù)
that = that || window;
var n = this.name; // 函數(shù)名
// 修改函數(shù)名篡悟,以防與對(duì)象中其他屬性沖突
n += (Math.random() + '').slice(2, 12) + new Date() * 1;
that[n] = this;
// 將函數(shù)賦給對(duì)象
var res = that[n](...argu);
delete that[n];
return res;
}
封裝bind
Function.prototype.mBind = function (that, ...arg) {
that = that || window;
var _self = this;
return function () {
return _self.apply(that, arg.concat(...arguments));
}
}
總結(jié)
1,當(dāng)我們使用一個(gè)函數(shù)需要改變this指向的時(shí)候才會(huì)用到call apply bind
2,如果你要傳遞的參數(shù)不多谜叹,則可以使用fn.call(thisObj, arg1, arg2 ...)
3,如果你要傳遞的參數(shù)很多匾寝,則可以用數(shù)組將參數(shù)整理好調(diào)用fn.apply(thisObj, [arg1, arg2 ...])
4,如果你想生成一個(gè)新的函數(shù)長(zhǎng)期綁定某個(gè)函數(shù)給某個(gè)對(duì)象使用,則可以使用const newFn = fn.bind(thisObj); newFn(arg1, arg2...)