Open wingmeng opened 5 years ago
ECMAScript 中的 call() 方法使用一个指定的 this 值和单独给出的一个或多个参数来调用一个函数。 下面我们编写一个函数 myCall 来模拟 call 方法,以此加深对 call 的理解。
call()
myCall
call
// 将 myCall 定义在 Function 原型链上,这样所有的函数都可以共享这个方法 // context 为当前上下文环境 Function.prototype.myCall = function(context, ...args) { // 当传入 null 或 undefined 时,指向 window context = context || window; // 【重点】 // 在当前上下文环境下创建一个临时函数,赋值为 this(当前调用 myCall 的函数) // 用以将当前调用 myCall 的函数“借用”到当前上下文环境中 context._fn = this; // 将形参传入临时函数,获得执行结果 let result = context._fn(...args); // 过河拆桥,删除临时函数 delete context._fn; return result; }
但 call 方法是 ES1.3 就有了的,用 ES6 模拟未免有点……所以:
Function.prototype.myCall = function(context) { // 创建一个数组来保存参数,即考虑 bar.call(obj, a, b, c) 这样存在多参数的场景 var args = []; context = context || window; context._fn = this; // 接着要处理传参的问题,例如有多个参数的情况 // arguments 是函数中的隐式参数,保存着传递递给函数的实参,是一个伪数组(像数组却没有数组方法) // 注意这里的 i 是从 1 开始的,因为 arguments[0] 是 context,排除在外 for (var i = 1; i < arguments.length; i++) { // 以形参的形式将参数保存到 args 数组中,供下一步使用 args.push('arguments[' + i + ']'); } // 【重点】 // 现在我们需要把临时函数和参数以字符串的形式拼接起来,然后用 eval 执行 // 为啥要用拼接的方式?因为 ES3 中无法给函数传递不定参数 var result = eval('context._fn(' + args + ')'); delete context._fn; return result; }
ECMAScript 中的
call()
方法使用一个指定的 this 值和单独给出的一个或多个参数来调用一个函数。 下面我们编写一个函数myCall
来模拟call
方法,以此加深对call
的理解。使用 ES6 实现,非常简单:
但
call
方法是 ES1.3 就有了的,用 ES6 模拟未免有点……所以:使用 ES3 实现: