2014-02-21 89 views
1
var any = _.some = _.any = function(obj, predicate, context) { 
    predicate || (predicate = _.identity); 
    var result = false; 
    if (obj == null) return result; 
    if (nativeSome && obj.some === nativeSome) return obj.some(predicate, context); 
    each(obj, function(value, index, list) { 
     if (result || (result = predicate.call(context, value, index, list))) return breaker; 
    }); 
    return !!result; 
    }; 

以上是在underscore.js中实现_.any方法。
在下面的行为谓词方法的结果进行测试时,为什么在这种情况下需要额外的检查?

if (result || (result = predicate.call(context, value, index, list))) 

result是从一开始就false,并且当result变量是通过调用predicate功能设置为true循环终止。所以在我看来,result变量的第一个检查总是会评估为false。为什么有这个变量的额外测试?

+0

结果可以在each()回调中随时设置。如果结果不是虚假的,each()函数会尽早终止,就像真正的[] .some()那样,下划线将会关闭并放慢速度... – dandavis

+0

@dandavis结果只能由predicate.call()设置,否? – Yeonho

回答

2

,我发现这个GitHub上的问题由lshearer

当本地的forEach功能存在,如果_.any是带一个 列表中的最后一个项目未通过真相测试 总是返回false(即使列表中的任何其他项目通过了 真相测试)。问题是本地forEach功能不会 短路(返回断路器;对其没有影响)。因此,调用_.any的 返回结果将被最后一个 项目覆盖。

https://github.com/jashkenas/underscore/issues/177

如果你看看each实施它使用本地的forEach(如果可用)。

// The cornerstone, an `each` implementation, aka `forEach`. 
// Handles objects with the built-in `forEach`, arrays, and raw objects. 
// Delegates to **ECMAScript 5**'s native `forEach` if available. 
var each = _.each = _.forEach = function(obj, iterator, context) { 
    if (obj == null) return obj; 
    if (nativeForEach && obj.forEach === nativeForEach) { 
    obj.forEach(iterator, context); 
    } else if (obj.length === +obj.length) { 
    for (var i = 0, length = obj.length; i < length; i++) { 
     if (iterator.call(context, obj[i], i, obj) === breaker) return; 
    } 
    } else { 
    var keys = _.keys(obj); 
    for (var i = 0, length = keys.length; i < length; i++) { 
     if (iterator.call(context, obj[keys[i]], keys[i], obj) === breaker) return; 
    } 
    } 
    return obj; 
}; 

显然,额外的检查是必要的。

相关问题