回顾call apply bind用途
let obj = {
name:"obj1"
say:function(){
//输出arguments
console.log(arguments);
console.log(this.name);
}
let obj2 = {
name:"obj2";
}
obj.say();
obj.say.call(obj2,1,2,3);
obj.say.apply(obj2,[1,2,3]);
sayClone = obj.bind(obj,1,2,3);
sayClone();
}
原生实现bind()
bind的特点:
- 接受调用传参和新建对象构造函数传参
- 如果是外部没有传入this就要新建一个this
- 和call接受的参数和实现的回调功能一样
- 返回的是一个新创建的原来传入的this克隆的对象
//函数的构造函数 : Function
//用es6解构rest的方式传参
Function.prototype.myBind = function(objThis,...params){
//定义指向当前函数this的指针
const thisTn = this;
//因为最终返回的是一个函数,所以声明一个函数返回
//用let表示块作用域
let funcForBind = function(...secondParams){
/*因为例如
let sayClone = obj.say.bind(obj2,1,2,3);
sayClone(4);
这里还是可以进行传参,最终传的就是1,2,3,4,所以可以用解构 ...secondParams
*/
//判断是不是新创建的对象 如果新创建的对象的话 this就是当前函数的this 不是新创建的话就是传进来的那个对象的上下文
const isNew = this instanseof funcForBind;
const thisArg = isNew ? this : objThis;
//返回调用 并分别解构传入的参数params和创建对象传入的参数secondParams
return thisFn.call(thisArg,...params,...secondParams);
}
//因为bind返回的是克隆的对象,所以还要把原型链进行克隆
funForBind.prototype = Object.create(thisFn.prototype);
return funcForBind;
}
原生实现call()和apply()
之前的例子:
//给obj2增加一个obj的call的函数,然后用传入的参数进行调用返回最终值
obj.say.call(obj2,1,2,3);
Function.prototype.myCall = function(thisArg,...arr){
if(thisArg == null || thisArg == undefined){
thisArg = window;
}
//定义一个不重复的方法名称
const specialMethod = Symbol('anything');
//将这个不重复的方法Function的指针给thisArg的specialMethod方法
thisArg[specialMethod] = this;
//调用函数并结果返回
let result = thisArg[specialMethod](...arr);
//delete 新增的属性
delete thisArg[specialMethod];
return result;
}
obj.say.myCall(obj2,1,2,3);
Function.prototype.myApply = function(thisArg,arr){
if(thisArg == null || thisArg == undefined){
thisArg = window;
}
//定义一个不重复的方法
const specialMethod = Symbol('anything');
//将这个不重复的方法的指针给thisArg的specialMethod方法
thisArg[specialMethod] = this;
//调用函数并结果返回
let result = thisArg[specialMethod](...arr);
//delete 新增的属性
delete thisArg[specialMethod];
return result;
}
obj.say.myApply(obj2,[1,2,3]);