- call
Function.prototype.myCall = function(context) {
if(typeof this !== 'function') {
return;
}
// context 不傳入或為 null察绷,可指向 window
context = Object(context) || window;
context.fn = this;
const args = [...arguments].slice(1);
const result = context.fn(...args);
delete context.fn;
return result;
}
- apply
Function.prototype.myApply = function(context, arr) {
context = Object(context) || window;
context.fn = this;
let result;
if(!arr) {
result = context.fn();
} else {
result = context.fn(...arguments[1]);
}
delete context.fn;
return result;
}
- bind
bind() 方法會創(chuàng)建一個新函數(shù)。當這個新函數(shù)被調(diào)用時津辩,bind() 的第一個參數(shù)將作為它運行時的 this拆撼,之后的一序列參數(shù)將會在傳遞的實參前傳入作為它的參數(shù)。
Function.prototype.myBind = function(context) {
const self = this;
// 獲取 bind 函數(shù)從第二個參數(shù)到最后一個參數(shù)
const args = [...arguments].slice(1);
return function() {
return self.apply(context, args.concat(...arguments))
}
}
bind 還有一個特點喘沿,就是 一個綁定函數(shù)也能使用new操作符創(chuàng)建對象:這種行為就像把原函數(shù)當成構造器闸度。提供的 this 值被忽略,同時調(diào)用時的參數(shù)被提供給模擬函數(shù)蚜印。
也就是說當 bind 返回的函數(shù)作為構造函數(shù)的時候莺禁,bind 時指定的 this 值會失效,但傳入的參數(shù)依然生效窄赋。
Function.prototype.myBind2 = function(context) {
const self = this;
// 獲取 bind 函數(shù)從第二個參數(shù)到最后一個參數(shù)
const args = [...arguments].slice(1);
return function Fn() {
// 可以當構造函數(shù)調(diào)用
if(this instanceof Fn) {
return new self(...args, ...arguments)
}
return self.apply(context, args.concat(...arguments))
}
}
分析:
bind 返回一個函數(shù)哟冬,函數(shù)有兩種調(diào)用方式,一是直接調(diào)用忆绰,二是用 new 的方式當做構造函數(shù)調(diào)用
- 直接調(diào)用:因為 bind可以這樣使用:
fn.bind(obj, 1, 2)(3, 4)
所以需要把參數(shù)拼接即args.concat(...arguments)
- new 調(diào)用:需忽略 this