JavaScript Call函数原理

call原理分析,一定要看最后的例子。

1.call使用例子

function add(c, d) {
  return this.a + this.b + c + d;
}

const obj = { a: 1, b: 2 };

console.error(add.call(obj, 3, 4)); // 10

2.其实现原理类似于下面代码

const obj = {
  a: 1,
  b: 2,
  add: function(c, d) {
    return this.a + this.b + c + d
  }
};
console.log(obj.add(3,4)); //10

其步骤伪码

// 1. 将函数设为对象的属性
 obj.fn = add
// 2. 执行该函数
 obj.fn()
// 3. 删除该函数
 delete obj.fn

3. 实现

3.1基于ES3实现call

Function.prototype.es3Call = function (context) {
  var content = context || window;
  content.fn = this;
  var args = [];
  // arguments是类数组对象,遍历之前需要保存长度,过滤出第一个传参
  for (var i = 1, len = arguments.length ; i < len; i++) {
    // 避免object之类传入
    args.push('arguments[' + i + ']');
  }
  var result = eval('content.fn('+args+')');
  delete content.fn;
  return result;
}
console.error(add.es3Call(obj, 3, 4)); // 10

3.2基于ES6实现call,es6的rest参数

Function.prototype.es6Call = function (context) {
    var context = context || window;
    context.fn = this;
    var args = [];
    for (var i = 1, len = arguments.length; i < len; i++) {
        args.push(arguments[i]);
    }
    const result = context.fn(...args);
    delete content.fn;
    return result;
}

4.例子

测试一下自己是否真的理解了call

function fn1(){
   console.log(1);
}
function fn2(){
    console.log(2);
}

fn1.call(fn2);     //输出 1
 
fn1.call.call(fn2);  //输出 2

分析

/**
* fn1.call(fn2)
* fn2.fn = fn1
* fn2.fn()
* delete fn2.fn
*
* fn1.call.call(fn2)
* fn2.fn=fn1.call
* fn2.fn()->fn2.call()->递归->最后执行window.fn2()
* delete fn2.fn
*/

参考博客:

https://www.cnblogs.com/donghezi/p/9742778.html (例子分析太复杂了,让人难以理解)

https://blog.csdn.net/u010377383/article/details/80646415 (原理讲的很好)

猜你喜欢

转载自www.cnblogs.com/SmilingEye/p/11401099.html