理解并手写 bind() 函数
有了对call()、apply()的前提分析,相信bind()我们也可以手到擒来。
参考前两篇:'对call()函数的分析' 和 '对apply()函数的分析',我们可以先得到以下代码:
Function.prototype.myBind = function(obj){ // 判断调用对象是否为函数 if(typeof this !== 'function'){ console.error('type error!') } // 判断绑定的对象 obj = obj || window; }
bind()函数与call()函数参数的格式相同,不同的是bind()返回的是一个函数。
Function.prototype.myBind = function(obj){ if(typeof this !== 'function'){ console.error('type error!') } obj = obj || window; // 获取正确参数 let args = [...arguments].slice(1); // 返回函数 return function Fn(){}; }
使用bind()函数来对this进行绑定,可以之间在内部使用 apply() 。
Function.prototype.myBind = function(obj){ if(typeof this !== 'function'){ console.error('type error!') } obj = obj || window; let args = [...arguments].slice(1); return function Fn(){ // 直接使用apply() return this.apply(); }; }
这个时候会发现,我们绑定的this是window,而不是我们想要的’this‘环境,可以使用that作为中间量。
Function.prototype.myBind = function(obj){ if(typeof this !== 'function'){ console.error('type error!') } obj = obj || window; // 在这里借助that that = this; let args = [...arguments].slice(1); return function Fn(){ return that.apply(); }; }
然后我们需要考虑apply()中传递的参数,这里我们使用数组的concat()方法,得到apply中传递的数组。
Function.prototype.myBind = function(obj){ if(typeof this !== 'function'){ console.error('type error!') } obj = obj || window; that = this; let args = [...arguments].slice(1); return function Fn(){ // 传递两个参数(绑定对象,数组) return that.apply(obj,args.concat(...arguments)); }; }
最后需要判断函数作为构造函数的情况,这个时候需要传入当前函数的 this 给 apply 调用,其余情况都传入指定的上下文对象。
Function.prototype.myBind = function(obj){ if(typeof this !== 'function'){ console.error('type error!') } obj = obj || window; that = this; let args = [...arguments].slice(1); return function Fn(){ // 根据调用方式,传入不同绑定值 return that.apply(
this instanceof Fn ? this : obj, args.concat(...arguments)); }; }
最后通过一个例子,来验证是否达到bind()的功能要求。
Function.prototype.myBind = function(obj){ if(typeof this !== 'function'){ console.error('type error!') } obj = obj || window; that = this; let args = [...arguments].slice(1); return function Fn(){ return that.apply( this instanceof Fn ? this : obj, args.concat(...arguments)
);
} } let dog = { name: '狗', eat(food1, food2) { console.log(this.name + '爱吃' + food1 + food2); } } let cat = { name: '猫', } dog.eat.bind(cat, '鱼', '肉')(); // 猫爱吃鱼肉 dog.eat.mybind(cat, '鱼', '肉')(); // 猫爱吃鱼肉
本文来自博客园,作者:辉太狼`,转载请注明原文链接:https://www.cnblogs.com/HuiTaiLang1216/p/15979296.html