fn() 和 fn.call(null) 的区别?

题目描述

代码中使用了 fn.call(null) 写法,这里直接使用 fn() 是否合理?或者说哪些情况时将会不符合预期。

题目来源及自己的思路

axios 的 utils 源码关于 forEach 的实现

我的理解 fn.call(null) 此时 this 会指向 window(浏览器环境),但是这里直接使用 fn() 是否可以

相关代码

function forEach(obj, fn) {
  // Don't bother if no value provided
  if (obj === null || typeof obj === 'undefined') {
    return;
  }

  // Force an array if not already something iterable
  if (typeof obj !== 'object') {
    /*eslint no-param-reassign:0*/
    obj = [obj];
  }

  if (isArray(obj)) {
    // Iterate over array values
    for (var i = 0, l = obj.length; i < l; i++) {
      fn.call(null, obj[i], i, obj);
    }
  } else {
    // Iterate over object keys
    for (var key in obj) {
      if (Object.prototype.hasOwnProperty.call(obj, key)) {
        fn.call(null, obj[key], key, obj);
      }
    }
  }
}

你期待的结果是什么?实际看到的错误信息又是什么?

很多时候不太理解 call 的实战使用场景

阅读 1.9k
1 个回答

这是做了兼容性处理,所以不能用fn()替代的。
在调用forEach的时候,fn可能是一个纯函数,也可能是一个实例的方法,所以call(null)的作用是防止fn中使用了this,且this指向了原始实例引起的错误。

function Ooo() {
    this.a = 5;
    this.calc = function(v) {
        if (isNaN(n)) return NaN;
        return Math.pow(n, n);
    }
}

const it0 = new Ooo();
it0.calc(undefined); // 得到5的5次方
it0.calc.call(null, undefined); // 得到NaN

这个代码很怪,但是不重要,因为写函数(forEach)的人是不能确定调用者会传入的fn是什么样子的。而且,如果fn中对this强依赖直接报错,也是目的之一。

已参与了 SegmentFault 思否社区 10 周年「问答」打卡 ,欢迎正在阅读的你也加入。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题