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

时间:2017-05-23 22:53:36

标签: javascript underscore.js

我在Underscore的_.each功能中遇到了一些令人困惑的行为。我在基类中有以下内容,用于创建一组对象:

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();
}

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

有问题的子类的当前状态是:

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
  });
}

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

.each

突然,所有属性都出现在对象中,我的测试通过了!由于单行箭头函数(没有括号)返回其单个表达式的值(而多行箭头函数默认返回undefined),而表达式_.chain(properties) .keys() .reject((k) => k === 'id' || k === '_id') .each((k) => { console.log(k); this[k] = properties[k]; }) .value(); 返回bar,我唯一的结论是从foo = bar返回false结束了循环。

所以,我开始调查为什么会这样。我抓住了Underscore源代码(v1.8.3,运行相同的版本)来查看是否有专门用于完成该结果的特殊处理(这将方便地允许_.each的客户端代码来自{{ 1}}循环):

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)返回false时,这里没有什么可以提前爆发。

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

1 个答案:

答案 0 :(得分:3)

您好像使用的是lodash而不是underscore

来自lodash documentation

  

使用三个参数调用iteratee:(value,index | key,collection)。 Iteratee函数可以通过显式返回false 来提前退出迭代。