理解并手写 call() 函数
手写自己的call,我们要先通过call的使用,了解都需要完成些什么功能?
我们把手写的函数起名为myCall,obj作为形参承载传过来的第一个参数(即绑定的对象)。
Function.prototype.myCall = function(obj){}
call的调用对this的指向进行了改变,而this是函数,这是前提(对this进行判断)。
Funtion.prototype.myCall = function(obj){ // 判断调用对象是否为函数 if(typeof this !== 'function'){ console.error('type error') } }
同理应当判断是否传入了参数,如果没有传入参数,则绑定的对象设置为window。
Funtion.prototype.myCall = function(obj){ if(typeof this !== 'function'){ console.error('type error') } // 判断绑定的对象 obj = obj || window; }
要调用这个this方法,我们可以先将其作为对象的属性方法,然后调用。
Function.prototype.myCall = function(obj){ if(typeof this !== 'function'){ console.error('type error!'); } obj = obj || window; // 添加属性方法,并调用 obj.fn = this; obj.fn(); }
call调用完后,拥有使用完方法后的返回值,所以肯定要将方法的执行结果保存并返回。
Function.prototype.mycall = function(obj){ if(typeof this !== 'function'){ console.error('type error!') } obj = obj || window; obj.fn = this; // 将执行结果保存,并返回 let result = obj.fn(); return result; }
在原对象中,并没有obj.fn属性,所以我们要将其进行删除。
Function.prototype.mycall = function(obj){ if(typeof this !== 'function'){ console.error('type error!') } obj = obj || window; obj.fn = this; let result = obj.fn(); // 删除context.fn属性 delete obj.fn; return result; }
最后考虑下方法中使用的参数(从传递过来的第二个参数开始),通过slice()进行切割,并拼凑为数组。
Function.prototype.mycall = function(obj){ if(typeof this !== 'function'){ console.error('type error!') } // 获取正确参数 let args = [...arguments].slice(1) obj = obj || window; obj.fn = this; let result = obj.fn(...args); delete obj.fn; return result; }
最后通过一个例子,来验证是否达到call()的功能要求。
Function.prototype.myCall = function(obj) { if (typeof this !== 'function') { console.error('type error!'); } obj = obj || window; let args = [...arguments].slice(1); obj.fn = this; let result = obj.fn(...args) delete obj.fn; return result; } let dog = { name: '狗', eat(food1, food2) { console.log(this.name + '爱吃' + food1 + food2); } } let cat = { name: '猫', } dog.eat.call(cat, '鱼', '肉'); // 猫爱吃鱼肉 dog.eat.myCall(cat, '鱼', '肉'); // 猫爱吃鱼肉
另外两篇:'对apply()函数的分析' 和 '对bind()函数的分析' 。
本文来自博客园,作者:辉太狼`,转载请注明原文链接:https://www.cnblogs.com/HuiTaiLang1216/p/15974486.html