从下划线返回 false each 似乎结束了循环

Returning false from underscore each appears to end the loop

我在使用 Underscore 的 _.each 函数时遇到了一些莫名其妙的行为。对于我正在创建的一组对象,我在基础 class 中有以下内容:

constructor(properties = {}, options = {}) {
  // lets me replace UUID generator function for testing, and for a
  // special-case id used by a singleton subclass
  _.defaults(options, {generateUuid});
  _.chain(properties)
      .keys()
      .reject((k) => k === 'id' || k === '_id')
      .each((k) => this[k] = properties[k])
      .value();
  this._id = options.generateUuid();
}

在测试我的第一个大型子class 的构造函数时,我传入了大量属性(数字、字符串和布尔值)。我的 Chai 断言在第 43 个 属性(共 61 个)处失败,紧接在第一个 false 值之后。该错误声称 属性 不存在。

有问题的子class的当前状态很简单:

constructor(properties = {}) {
  if (typeof properties.subtype !== 'undefined') {
    properties._subtype = properties.subtype;
  }
  // etc. for several more aliased properties
  _.defaults(properties, {
    _subtype: 'token',
    // etc. for default property values
  });
  super({
    _type: 'graphic',
    _subtype: properties._subtype,
    // etc. for all whitelisted properties
  });
}

在尝试调试问题时,我确认所有属性及其正确值都已传递给 superclass 构造函数,但第一个 false 之后的所有属性都没有传递加入 this。只有当我向 .each 添加跟踪调试时,事情才真正改变:

_.chain(properties)
    .keys()
    .reject((k) => k === 'id' || k === '_id')
    .each((k) => {
      console.log(k);
      this[k] = properties[k];
    })
    .value();

突然间,对象中出现了所有属性,我的测试通过了!由于单行箭头函数(不带括号)返回其单个表达式的值(而多行箭头函数默认返回未定义),并且表达式 foo = bar returns bar,我的唯一的结论是从 _.each 返回 false 结束循环。

所以,我着手调查为什么会这样。我抓取了 Underscore 源代码(v1.8.3,与我 运行 相同的版本),看看是否有专门的特殊处理来实现该结果(这将方便地允许客户端代码 break 来自_.each 循环):

_.each = _.forEach = function(obj, iteratee, context) {
  iteratee = optimizeCb(iteratee, context);
  var i, length;
  if (isArrayLike(obj)) {
    for (i = 0, length = obj.length; i < length; i++) {
      iteratee(obj[i], i, obj);
    }
  } else {
    var keys = _.keys(obj);
    for (i = 0, length = keys.length; i < length; i++) {
      iteratee(obj[keys[i]], keys[i], obj);
    }
  }
  return obj;
};

context为假时,optimizeCb(iteratee, context)立即returnsiteratee。当 iteratee returns false.

时,这里没有什么应该提前爆发的

有人对我观察到的行为有解释吗?

您似乎在使用 lodash and not underscore

来自lodash documentation

The iteratee is invoked with three arguments: (value, index|key, collection). Iteratee functions may exit iteration early by explicitly returning false.