call的实现
原理:就是把一个要执行的函数,作为this指向的那个上下文的方法
实现:
Function.prototype.myCall = function (context, ...args) {
// 当上下文传的是一个null时,将上下文表示为window
var context = context || window;
// 判断类型
if (typeof this !== "function") {
throw Error("type error");
}
let key = Symbol("key");
// 将函数转为上下文的方法
context[key] = this;
// 执行函数
let result = context[key](...args);
//将属性删除
delete context[key];
return result;
};
apply的实现
原理和实现call方法类似
Function.prototype.myApply = function (context, arr) {
// 当传入null时 将上下文表示为window
context = context || window;
if (typeof this !== 'function') {
throw Error("type error")
}
let _this = Symbol("_this");
context[_this] = this;
let result = context[_this](...arr)
delete context[_this];
return result
}
bind实现
Function.prototype.myBind = function (context) {
// 判断类型
if (typeof this !== "function") {
throw new Error(
"Function.prototype.bind - what is trying to be bound is not callable"
);
}
var self = this;
// 截取传入的第二个参数
var args = Array.prototype.slice.call(arguments, 1);
var fNOP = function () {};
var fBound = function (innerArgs) {
// 这个时候的arguments是返回函数的参数
var bindArgs = innerArgs;
// 当作为构造函数时,this 指向实例,此时结果为 true,将绑定函数的 this 指向该实例,可以让实例获得来自绑定函数的值(当为构造函数时,让this指向失效)
// 当作为普通函数时,this 指向 window,此时结果为 false,将绑定函数的 this 指向 context
return self.apply(
this instanceof fNOP ? this : context,
args.concat(bindArgs)
);
};
//我们直接将 fBound.prototype = this.prototype,我们直接修改 fBound.prototype 的时候,也会直接修改绑定函数的 prototype
fNOP.prototype = this.prototype;
fBound.prototype = new fNOP();
return fBound;
}