underscore源码_.max函数写法疑问

underscore源码中求最大值的函数有一处比较使用的是:

if (value != null && value > result)

这里为什么要加多一个value != null的判断~难道还有value为null同时其又还比别的值大的情况?
对应函数源码如下:

_.max = function(obj, iteratee, context) {
    var result = -Infinity,
      lastComputed = -Infinity,
      value, computed;
    if (iteratee == null || (typeof iteratee == 'number' && typeof obj[0] != 'object') && obj != null) {
      obj = isArrayLike(obj) ? obj : _.values(obj);
      for (var i = 0, length = obj.length; i < length; i++) {
        value = obj[i];
        if (value != null && value > result) {
          result = value;
        }
      }
    } else {
      iteratee = cb(iteratee, context);
      _.each(obj, function(v, index, list) {
        computed = iteratee(v, index, list);
        if (computed > lastComputed || computed === -Infinity && result === -Infinity) {
          result = v;
          lastComputed = computed;
        }
      });
    }
    return result;
  };
阅读 3.2k
2 个回答

在Chrome的控制台:

null > 0 // false
null > -1 // true

采取这样的写法是因为更安全.
在开发的时候, 我们无法预知null与另外一个数值进行比较会产生什么样的结果,
或者说, 不是所有的JavaScript开发者都记住这样的以下规则:

当关系操作符的操作数使用了非数值时,也要进行数据转换或完成某些奇怪的操作。以下就是相应的规则。1

  • 如果两个操作数都是数值,则执行数值比较。

  • 如果两个操作数都是字符串,则比较两个字符串对应的字符编码值。

  • 如果一个操作数是数值,则将另一个操作数转换为一个数值,然后执行数值比较。

  • 如果一个操作数是对象,则调用这个对象的 valueOf()方法,用得到的结果按照前面的规则执行比较。如果对象没有 valueOf()方法,则调用 toString()方法,并用得到的结果根据前面的规则执行比

  • 如果一个操作数是布尔值,则先将其转换为数值,然后再执行比较。

所以, 从题主给出的源码来看, result的值是一个number, 而null与之比较则会转换成数值0:

null > 0  // false
null >= 0   // true
null < 0  // false
null <= 0  // true

所以我们显示的写明如果只有value != null的时候才进行数值比较,
从而避免null > result而导致预期外的结果的发生:

let value = null;
value > -1  // true
value > 0  // false

  1. 引自<<JavaScript高级程序设计(第3版)>>, 章节3.5.6-关系操作符
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题