call函数接受多个参数,第一个参数为函数上下文 this,后面参数是函数本身的参数。
首先先定义两个基本函数
let Person = {
name: 'Tom',
say(age, sex) {
console.log(this)
console.log(`我叫${this.name},我今年${age},性别:${sex}`)
}
}
Person1 = {
name: 'Tom1'
}
实现call
/**
* 自定义call实现
* @param context 上下文this对象
* @param args 动态参数
*/
Function.prototype.myCall = function (context, ...args) {
context = typeof context === 'object' ? context : window; // 没有传值,则指向window
const key = Symbol(); // 把key设置成唯一值,不影响context
context[key] = this; // this指的是 调用call的那个方法,在这里指得是 Person,因为是Person调用的
const result = context[key](...args); // 设置可以传参,用到了 rest 参数,处理剩余的参数
delete context[key]; // 最后还需要手动删除,否则 context 无缘无故多了个 key方法
return result; // 最后返回一下这个属性
}
Person.say.myCall(Person1, 18, '女') //我叫Tom1我今年18
apply和call一样,第一个参数为函数上下文this,后面参数是函数本身的,是以数组形式传入。
/**
* 自定义Apply实现
* @param context 上下文this对象
* @param args 参数数组
*/
Function.prototype.myApply = function (context, args) {
context = typeof context === 'object' ? context : window;
const key = Symbol();
context[key] = this;
const result = context[key](...args);
delete context[key];
return result;
}
Person.say.myApply(Person1, ['18', '女']) //我叫Tom1我今年18
bind接受多个参数,第一个是bind返回值,返回值是一个函数上下文 this,不会立即执行。
这里借用call实现
Function.prototype.myBind = function (context) {
context = typeof context === 'object' ? context : window;
return (...args) => {
this.call(context, ...args);
}
}
const myfun = Person.say.myBind(Person1);