手摸手带你实现call函数,重在思路
2021/11/27 23:15:22
本文主要是介绍手摸手带你实现call函数,重在思路,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
待会实现的自定义call函数,会用下面简单的函数调用系统的call函数进行对比
function foo() { console.log('foo函数执行', this); } function sum(num1, num2) { console.log('sum函数执行', this, num1, num2); return num1 + num2; }
一、给所有的函数添加一个 dycall 方法
系统的call 函数是可以直接被函数调用的,因此,我们自定义的 dycall 方法需要挂载到函数对象的原型上
Function.prototype.dycall = function() { console.log('dycall方法执行') }
foo.dycall();
二、获取被调用的函数
在自定义的 dycall 方法中,我们要获取到调用 dycall 方法的函数对象,然后在 dycall 方法中,进行调用
foo.dycall() 相当于 this 的隐式绑定,直接通过this获取被调用的函数对象
Function.prototype.dycall = function () { // 1.获取需要被执行的函数 var fn = this; fn(); }
三、dycall 方法绑定 传入的内容
传入空对象对比调用
foo.call({}); // foo函数执行 {}
foo.dycall({}); // foo函数执行 Window {...}
对比系统call调用,自定义的 dycall 方法this指向的是 window,因此绑定this,将获取的 fn 函数添加到传入的对象上,相当于this的隐式绑定,this就指向了传入的空对象
// 给所有函数添加一个 dycall 的方法 Function.prototype.dycall = function (thisArgs) { // 1.获取需要被执行的函数 var fn = this; thisArgs.fn = fn; thisArgs.fn(); };
foo.dycall({}); // foo函数执行 {fn: ƒ}
在此调用后,输出的this就是我们传入的空对象,但是对比系统call,我们多了绑定的 fn 函数,因此需要在dycall调用fn后,删除多余的属性。输出的时候会看到,但,无伤大雅
// 给所有函数添加一个 dycall 的方法 Function.prototype.dycall = function (thisArgs) { // 1.获取需要被执行的函数 var fn = this; thisArgs.fn = fn; // 2.调用需要被改变this的函数 thisArgs.fn(); delete thisArgs.fn; };
四、对比其他几种case,完善边界情况
- 传入对象
- 传入简单数据类型
foo.call(123); // foo函数执行 Number {123} foo.call("abc"); // foo函数执行 String {'abc'}
我们自定义的 dycall 绑定的this是对象,因此可以进行 fn 添加调用,如果传入的是简单数据类型,需要我们转换为对应类型的对象,需要使用到 Objecet(),方法
// 给所有函数添加一个 dycall 的方法 Function.prototype.dycall = function (thisArgs) { // 1.获取需要被执行的函数 var fn = this; // 2.将thisArgs转成对象类型(防止传入的是非对象类型),非对象类型不能添加属性 thisArgs = Object(thisArgs) thisArgs.fn = fn; // 3.调用需要被改变this的函数 thisArgs.fn(); delete thisArgs.fn; };
foo.dycall(123); // foo函数执行 Number {123, fn: ƒ} foo.dycall("abc"); // foo函数执行 String {'abc', fn: ƒ}
3.传入 null 、undefined 或 空参
foo调用系统call,this指向 Window
foo.call(); // foo函数执行 Window {...} foo.call(undefined); // foo函数执行 Window {...} foo.call(null); // foo函数执行 Window {...}
// 给所有函数添加一个 dycall 的方法 Function.prototype.dycall = function (thisArgs) { // 1.获取需要被执行的函数 var fn = this; // 2.将thisArgs转成对象类型(防止传入的是非对象类型),非对象类型不能添加属性 thisArgs = thisArgs ? Object(thisArgs) : window; thisArgs.fn = fn; // 3.调用需要被改变this的函数 thisArgs.fn(); delete thisArgs.fn; };
五、参数赋值以及返回值(最终版)
sum.call({}, 20, 30); // sum函数执行 {} 20 30
tips:用剩余运算符 ...args 接收多个参数,调用的时候使用 扩展运算符 ...args
// 给所有函数添加一个 dycall 的方法 Function.prototype.dycall = function (thisArgs, ...args) { // 1.获取需要被执行的函数 var fn = this; // 2.将thisArgs转成对象类型(防止传入的是非对象类型),非对象类型不能添加属性 thisArgs = thisArgs ? Object(thisArgs) : window; thisArgs.fn = fn; // 3.调用需要被改变this的函数 var result = thisArgs.fn(...args); delete thisArgs.fn; // 4.将调用后的结果返回 return result; };
这篇关于手摸手带你实现call函数,重在思路的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-26MATLAB 中 A(7)=[];什么意思?-icode9专业技术文章分享
- 2024-11-26UniApp 中如何实现使用输入法时保持页面列表不动的效果?-icode9专业技术文章分享
- 2024-11-26在 UniApp 中怎么实现输入法弹出时禁止页面向上滚动?-icode9专业技术文章分享
- 2024-11-26WebSocket是什么,怎么使用?-icode9专业技术文章分享
- 2024-11-26页面有多个ref 要动态传入怎么实现?-icode9专业技术文章分享
- 2024-11-26在 UniApp 中实现一个底部输入框的常见方法有哪些?-icode9专业技术文章分享
- 2024-11-26RocketMQ入门指南:搭建与使用全流程详解
- 2024-11-26RocketMQ入门教程:轻松搭建与使用指南
- 2024-11-26手写RocketMQ:从入门到实践的简单教程
- 2024-11-25【机器学习(二)】分类和回归任务-决策树(Decision Tree,DT)算法-Sentosa_DSML社区版