1. call-apply-bind三者的作用
在JavaScript中,call-apply-bind是Function对象自带的三种方法,它们的作用都是用来改变函数内的this指向,传递的第一个参数都是this所要指向的对象,而且它们三个都可以传递参数(后续传值)。
2. call-apply-bind三者的区别
obj.call(obj1,arg1,arg2,arg3....);
obj.apply(obj1,[arg1,arg2,arg3.....]);
obj.bind(obj1,arg1,arg2,arg3...)();
3. call-apply-bind三者的内部实现
在内部实现的时候,需要把函数绑定在Function原型上,是原型上面的方法
Function.prototype.myCall = function(context = window, ...args) {
if (this === Function.prototype) {
return undefined; //判断当前this是否为函数,用于防止Function.prototype.myCall()直接调用
}
context = context || window; //context为可选参数,如果不传的话,默认指向window
const fn = Symbol(); //利用symbol进行定义,可以保证不会重名
context[fn] = this; //将当前函数赋给这个属性,这样之后执行context[fn]的时候,fn里面的this指向就为context了
const result = context[fn](...args);
delete context[fn]; //调用完后立即删除symbol属性
return result;
}
//调用
let person1 = {
name:'王',
age:18,
say(...args){
console.log(`名字为${this.name},年龄为${this.age},参数为${args}`);
}
}
let person2 = {
name:'李',
age:20
}
person1.say.myCall(person2,1,2,3);
//输出 名字为李,年龄为20,参数为1,2,3
Function.prototype.myApply = function(context = window,args){
if(this === Function.prototype){
return undefined;
}
context = context || window;
const fn = Symbol();
context[fn] = this;
let result;
if(Array.isArray(args)){
result = context[fn](...args);
}else{
result = context[fn]();
}
delete context[fn];
return result;
}
//调用
let person1 = {
name:'王',
age:18,
say(...args){
console.log(`名字为${this.name},年龄为${this.age},参数为${args}`);
}
}
let person2 = {
name:'李',
age:20
}
person1.say.myApply(person2,[1,2,3]);
//输出 名字为李,年龄为20,参数为1,2,3
Function.prototype.myBind = function(obj,...args){
let self = this;
return function(){
let newArgs = args.concat(...arguments);
self.call(obj,newArgs);
}
}
//调用
let person1 = {
name:'王',
age:18,
say(...args){
console.log(`名字为${this.name},年龄为${this.age},参数为${args}`);
}
}
let person2 = {
name:'李',
age:20
}
person1.say.myBind(person2,1,2,3)(4,5);
//输出 名字为李,年龄为20,参数为1,2,3,4,5