call、apply和bind区别:
相同点:
作用相同,都是动态修改this指向;都不会修改原先函数的this指向。
异同点:
- 执行方式不同:
- call和apply是改变后页面加载之后就立即执行,是同步代码。
- bind是异步代码,改变后不会立即执行;而是返回一个新的函数。
- 传参方式不同:
- call和bind传参是一个一个逐一传入。
- apply可以使用数组的方式传入的 。
- call和 apply不能使用剩余参数的方式传参,bind 可以使用剩余参数的方式传入(柯里化)。
- 修改this的性质不同:
call、apply只是临时的修改一次,也就是call和apply方法的那一次;当再次调用原函数的时候,它的指向还是原来的指向。
1.手写call方法
- 定义myCall方法
- 设置this并调用原函数
- 接收剩余参数并返回结果
- 使用Symbol调优
//1.定义myCall方法
//3.接收剩余参数并返回结果
Function.prototype.myCall=function(thisArg,...args){
// 2.设置this并调用原函数
// thisArg:作为传入的设置为this的对象
// this:原函数(func)
console.log('thisArg:',thisArg);
console.log('this:',this)
// 给thisArg加一个一定和原属性不重名的新属性(方法)
const key = Symbol('key');
thisArg[key]=this;//动态增加的属性名,[]动态解析属性名解析为Symbol值
const res = thisArg[key](...args);
delete thisArg[key] // 删除原对象中动态添加的方法,保持原对象不被修改
// thisArg.fun=this;//如果采用thisArg.key的形式,相当于属性名就叫key
//const res = thisArg.fun(...args);
// delete thisArg.fun
return res
}
const person={
name:'小明'
}
function func(numA,numB){
console.log(this)
console.log(numA,numB)
return numA+numB
}
const res= func.myCall(person,2,8);//this指向person, 立即执行
console.log('返回值为:',res);//返回值:10
func(1,2);//this指向window
const food={
name:'面包'
}
function fun2(num1,num2,num3){
console.log(this);
console.log(num1,num2,num3);
return num1+num2+num3;
}
const res2=fun2.myCall(food,2,4,6);
console.log('res2:',res2);// res2: 12
2.手写apply方法
- 定义myApply方法
- 设置this并调用原函数
- 接收参数并返回结果
Function.prototype.myApply = function(thisArg,args){
const key = Symbol('key');
thisArg[key]=this;
const res = thisArg[key](...args);
delete thisArg[key]
return res
}
const food={
name:'面包'
}
function fun2(num1,num2,num3){
console.log(this);
console.log(num1,num2,num3);
return num1+num2+num3;
}
const res =fun2.myApply(food,[2,8,10]);//this指向food,以数组方式传入参数,立即调用执行
console.log('返回值为:',res)//20
funs(1,2,3);//this指向window
3.手写bind方法
- 定义myBind方法
- 返回绑定this的新函数
- 合并绑定和新传入的参数
// 1. 定义myBind方法
Function.prototype.myBind = function(thisArg,...args){
// 2.返回绑定this的新函数
return (...reArgs)=>{
// this:原函数(func)
//3. 合并绑定和新传入的参数
return this.call(thisArg,...args,...reArgs);
}
}
const person={
name:'小明'
}
function func(numA,numB,numC,numD){
console.log(this);
console.log(numA,numB,numC,numD)
return numA+numB+numC+numD
}
const bindFunc=func.myBind(person,1,2);
console.log('bindFunc:',bindFunc);// 函数, this指向person
const res=bindFunc(3,4); // 再次调用执行
console.log('返回值:',res);// 10