call,apply,bind分析
作用:
call 、bind 、 apply 这三个函数都是更改this指针的指向,重新定义方法中的this指向哪个对象。
举例:
var name = '王某',age = 17;
var obj={
name:'张某',
age: '1岁',
objAge:this.age,
outputInfo:function (sex,hobby){
console.log(this.name+' 年龄:'+this.age+' 性别:'+sex+' 爱好:'+hobby)
}
}
console.log(obj.objAge); // 17
obj.outputInfo(); //张某 年龄:1岁 性别:undefined 爱好:undefined
obj.outputInfo('男','玩游戏'); //张某 年龄:1岁 性别:男 爱好:玩游戏
在myFun函数外调用this.age 实际访问的是window对象 函数内的this指向obj。 如果新定义一个对象,但是想用一下 outputInfo 方法,就要用到call 、bind 、 apply
例如:
var obj={
name:'张某',
age: '1岁',
objAge:this.age,
outputInfo:function (sex,hobby){
console.log(this.name+' 年龄:'+this.age+' 性别:'+sex+' 爱好:'+hobby)
}
};
var newObj={
name: '小李',
age: '80岁'
};
obj.outputInfo.call(newObj,'男','穿裙子'); //小李 年龄:80岁 性别:男 爱好:穿裙子
obj.outputInfo.apply(newObj,['男','穿裙子']); //小李 年龄:80岁 性别:男 爱好:穿裙子
obj.outputInfo.bind(newObj,'男','穿裙子')(); //小李 年龄:80岁 性别:男 爱好:玩游戏
obj.outputInfo.bind(newObj,['男','穿裙子'])(); //小李 年龄:80岁 性别:['男','穿裙子'] 爱好:undefined
此时outputInfo函数中的 this 就会指向传入的 newObj 对象。
区别和不同:
- call,apply,bind的传参方法不同。
- bind与call、apply的调用方法不同,bind在使用后要再手动调用一下,.bind()();
- call 传参: 参数依次列举
- apply 传参: 参数放在数组或者类数组中作为第二个参数传入
- bind 传参: 与call一样依次列举
自己实现call,apply,bind
call方法
Function.prototype.myCall = function(context,...args){
//将当前被调用的方法定义在cxt.func上.(为了能以对象调用形式绑定this)
let cxt = context || window;
//新建一个唯一的Symbol变量避免重复
let func = Symbol();
cxt[func] = this;
args = args ? args : [];
//以对象调用形式调用func,此时this指向cxt 也就是传入的需要绑定的this指向
const res = args.length > 0 ? cxt[func](...args) : cxt[func]();
//删除该方法,不然会对传入对象造成污染(添加该方法)
delete cxt[func];
return res;
}
apply方法
Function.prototype.myApply = function(context,args = []){
//将当前被调用的方法定义在cxt.func上.(为了能以对象调用形式绑定this)
let cxt = context || window;
//新建一个唯一的Symbol变量避免重复
let func = Symbol();
cxt[func] = this;
const res = args.length > 0 ? cxt[func](...args) : cxt[func]();
//删除该方法,不然会对传入对象造成污染(添加该方法)
delete cxt[func];
return res;
}
bind方法
Function.prototype.myBind = function(context,...args){
//新建一个变量赋值为this,表示当前函数
const fn = this;
//判断有没有参数传进来,若为空则赋值[]
args = args ? args : [];
//返回一个newFn函数,在里面调用fn
return function newFn(...newFnArgs){
if(this instanceof newFn){
return new fn(...args,...newFnArgs)
}
return fn.apply(context,[...args,...newFnArgs])
};
}