三個(gè)函數(shù)都能改變this指向,且三者第一個(gè)參數(shù)都為指定的this對(duì)象。區(qū)別如下:
1、call 傳入?yún)?shù)列表,非數(shù)組; apply 參數(shù)格式為數(shù)組, bind參數(shù)列表。
2、call ,apply 為立即執(zhí)行函數(shù),bind 返回函數(shù)需要調(diào)用執(zhí)行。
call方法的實(shí)現(xiàn)
Function.prototype.myCall = function (context) {
// 先判斷調(diào)用myCall是不是一個(gè)函數(shù)
// 這里的this就是調(diào)用myCall的
if (typeof this !== 'function') {
throw new TypeError("Not a Function")
}
// 不傳參數(shù)默認(rèn)為window
context = context || window
// 保存this
context.fn = this
// 保存參數(shù)
let args = Array.from(arguments).slice(1) //Array.from 把偽數(shù)組對(duì)象轉(zhuǎn)為數(shù)組
// 調(diào)用函數(shù)
let result = context.fn(...args)
delete context.fn
return result
}
apply方法的實(shí)現(xiàn)
Function.prototype.myApply = function (context) {
// 判斷this是不是函數(shù)
if (typeof this !== "function") {
throw new TypeError("Not a Function")
}
let result
// 默認(rèn)是window
context = context || window
// 保存this
context.fn = this
// 是否傳參
if (arguments[1]) {
result = context.fn(...arguments[1])
} else {
result = context.fn()
}
delete context.fn
return result
}
bind方法的實(shí)現(xiàn)
if (!Function.prototype.bind) {
Function.prototype.bind = function (oThis) {
if (typeof this !== "function") {
// closest thing possible to the ECMAScript 5
// internal IsCallable function
throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");
}
var aArgs = Array.prototype.slice.call(arguments, 1),
fToBind = this,
fNOP = function () {},
fBound = function () {
return fToBind.apply(this instanceof fNOP
? this
: oThis || this,
aArgs.concat(Array.prototype.slice.call(arguments)));
};
fNOP.prototype = this.prototype;
fBound.prototype = new fNOP();
return fBound;
};
}
注意:在非嚴(yán)格模式下,第一個(gè)參數(shù)沒傳默認(rèn)是window,在嚴(yán)格模式下是undefined,手寫沒考慮全面。