是否需要此或(||)语句?

时间:2013-06-28 14:12:24

标签: javascript underscore.js

在下划线的最新代码here中,在第211行读取

result || (result = iterator.call(context, value, index, list))) return breaker;

是需要的还是声明?可以用

代替
(result = iterator.call(context, value, index, list))) return breaker; // ?

result最初设置为false,除了这一行之外,代码中没有其他地方被修改。

请注意,JavaScript或(||)语句返回第一个操作数(如果它是真实的),第二个操作数(如果它'是第一个操作数)是假的。这是直接来自Crockford,Good Parts。还注意到||做一个或与truthy / falsy值不是真/假值。

以下是从上面链接转载的整个方法:

var any = _.some = _.any = function(obj, iterator, context) {
    iterator || (iterator = _.identity);
    var result = false;
    if (obj == null) return result;
    if (nativeSome && obj.some === nativeSome) return obj.some(iterator, context);
    each(obj, function(value, index, list) {
      if (result || (result = iterator.call(context, value, index, list))) return breaker;
    });
    return !!result;
  };

2 个答案:

答案 0 :(得分:7)

这让我觉得result||检查只是为了以防万一...或支持定义forEach的环境(例如通过垫片),但some不是。< / p>

正如评论中所指出的,由于以下几个原因,下划线依赖本机循环方法(forEachmap和朋友)似乎并不是一个好主意:

  • 他们是slower而不是简单的循环
  • 你不能破解(好吧,你可能有一个专门的例外,但是下划线不会这样做)
  • Array.prototype可被其他(恶意或愚蠢)代码篡改

答案 1 :(得分:3)

答案是:,可以按建议的方式进行优化如果是原生代码

为了理解将会发生什么,让我们将代码简化为重要的事项,首先:

var result = false;
for (var i in obj)
{
    if (result || (result = call(i)))
        return;
}

这意味着,如果result已经非假,它将返回,或者如果call()返回非假值,它将返回。由于结果仅由call()更改,因此对result的首次检查是多余的。

var result = false;
for (var i in obj)
{
    if (result = call(i))
        return;
}

只要call()传递了非假值,此代码仍会返回。

此外,each()是一个库函数,OP在找到的项目上返回breaker

真正发生的是:

var result = false;
for (var i in obj)
{
    if (result || (result = call(i)))
        break;
}

在这种情况下,只要使用了librarys foreach函数,代码仍然可以以建议的方式进行优化。循环将保留在找到的值上。

令人困惑的部分是each()是一个库函数,它使用一个函数来模拟循环体。从body函数返回库常量breaker将退出循环。

只要each()决定使用原生.forEach() ,代码就无法优化,因为.forEach()无法理解breaker的返回值1}}!有关详细信息,请参阅 thg435 的答案!