call方法作用
调用一个对象的一个方法,以另一个对象替换当前对象。也就是说改变方法中this指向,第一个参数代表this指向的对象,后面紧跟的参数为函数原有的形参
call方法的使用
const A = {
name: '我是A对象的name',
getName: function () {
console.log(this.name);
},
};
const B = {
name: '我是B对象的name'
}
A.getName() // //结果 我是A对象的name
A.getName.call(B) //结果 我是B对象的name
- 使用call改变了A对象中getName方法的this指向,使其指向了B对象
- fn.call(obj)可以看成obj.fn(...args),这样fn中的this就指向了obj
- 我们可以使用call方法,借助其他对象中存在的方法实现自己的功能,例如es5将伪数组转为真正的数组,new 关键字的实现也借助了call方法等
call方法的参数
const A = {
name: '我是A对象的name',
getName: function (a,b,c) {
console.log(this.name,a+b+c);
},
};
const B = {
name: '我是B对象的name'
}
A.getName(2,3,4) // //结果 我是A对象的name 9
A.getName.call(B,1,2,3) //结果 我是B对象的name 6
- call方法第一个参数为this指向的对象,后面的参数为原方法中的参数,依次传递
- fn.apply(obj)可以看成obj.fn([...args]),这样fn中的this就指向了obj
- call的语法:函数名.call(obj,参数1,参数2,参数3...)
自定义call方法
const A = {
name: '我是A对象的name',
getName: function (a,b,c) {
console.log(this.name,a+b+c);
},
};
const B = {
name: '我是B对象的name'
}
//call前面是fucntion函数,所以该方法需要添加到Function构造函数的原型对象上
Function.prototype.myCall = function (context,...args) {
if(typeof this !== 'function'){
throw new Error(`${this} is not function`)
}
if(!context instanceof Object){
throw new Error(`${context} is not Object`)
}
//将函数绑定到对象上作为对象上的方法
context.fn = this
//执行对象中的方法
const result = context.fn(...args)
//删除被绑定的方法
delete context['fn']
return result
}
A.getName.myCall(B,1,2,3) //我是B对象的name 6
A.getName.call(B,1,2,3) //我是B对象的name 6
apply与call对比
-
功能相同,都是改变this指向
-
语法不同 apply的语法:函数名.call(obj,[参数1,参数2,参数3...])
apply方法的使用
const A = {
name: '我是A对象的name',
getName: function (a,b,c) {
console.log(this.name,a+b+c);
},
};
const B = {
name: '我是B对象的name'
}
A.getName.apply(B,[1,2,3]) //输出 我是B对象的name 6
自定义apply方法
const A = {
name: '我是A对象的name',
getName: function (a,b,c) {
console.log(this.name,a+b+c);
},
};
const B = {
name: '我是B对象的name'
}
Function.prototype.myApply = function (context,args) {
if(typeof this !== 'function'){
throw new Error(`${this}is not function` )
}
if(!context instanceof Object){
throw new Error(`${context} is not Object`)
}
if(args && !Array.isArray(args)){
throw new Error(`${args} is not Array`)
}
context.fn = this
const result = context.fn(...args)
return result
}
A.getName.myApply(B,[1,2,3]) //输出 我是B对象的name 6
bind与apply和call对比
- 功能相同,都是改变this指向
- 返回值不同,bind会返回一个函数,我们需要调用这个返回值
- 入参与call相同
bind方法的使用
const A = {
name: '我是A对象的name',
getName: function (a,b,c) {
console.log(this.name,a+b+c);
},
};
const B = {
name: '我是B对象的name'
}
A.getName.bind(B)(1,2,3) //输出 我是B对象的name 6
自定义bind方法
const A = {
name: '我是A对象的name',
getName: function (a,b,c) {
console.log(this.name,a+b+c);
},
};
const B = {
name: '我是B对象的name'
}
Function.prototype.myBind = function (context) {
const self = this;
if (typeof self !== "function") {
throw new Error(`${self}is not function`);
}
if (!context instanceof Object) {
throw new Error(`${context} is not Object`);
}
//bin方法返回一个函数
return function (...args) {
context.fn = self
const result = context.fn(...args);
return result;
};
};
A.getName.myBind(B)(1, 2, 3); //输出 我是B对象的name 6