【JavaScript】原生实现call bind apply 回顾call apply bind用途 原生实现bind() 原生实现call()和apply()

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的特点:

  1. 接受调用传参和新建对象构造函数传参
  2. 如果是外部没有传入this就要新建一个this
  3. 和call接受的参数和实现的回调功能一样
  4. 返回的是一个新创建的原来传入的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]);