zoukankan      html  css  js  c++  java
  • 【JavaScript】原生实现call bind apply

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

    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]);
    
  • 相关阅读:
    从a文件判断是否删除b文件中的行(sed示例)
    绝对路径的表示方式为什么是"/usr"而不是"//usr"
    判断ssh远程命令是否执行结束
    彻底搞懂shell的高级I/O重定向
    Resource Agent:LSB和OCF
    流程控制语句(MySQL/MariaDB )
    MySQL/MariaDB中游标的使用
    翻译:DECLARE HANDLER语句(已提交到MariaDB官方手册)
    从集合的无序性看待关系型数据库中的"序"
    MariaDB/MySQL存储过程和函数
  • 原文地址:https://www.cnblogs.com/SiriusZHT/p/14310756.html
Copyright © 2011-2022 走看看