underscore.js every()with undefined

时间:2013-10-10 14:00:08

标签: javascript underscore.js

我写了一些这样的代码:

var a = new Array(10); // should be [undefined * 10] 
var b = _.every(a, function(m){
    if(_.isUndefined(m)){
        return false;
    }
    return true;
});

我希望b是'假',但它返回'true'。 为什么它会返回'true'?

然后,我改为:

var c = [undefined, undefined];
var d = _.every(c, function(m){
    if(_.isUndefined(m)){
        return false;
    }
    return true;
});

它在d。

中返回'false'

为什么他们不同?

您可以在http://jsfiddle.net/3qj4B/3/

中对此进行测试

2 个答案:

答案 0 :(得分:2)

使用Array构造函数初始化数组与初始大小之间存在细微差别,并使用undefined条目的显式列表进行初始化。前者(Array构造函数)不会创建与索引对应的属性,而显式初始化则会创建。

我怀疑Underscore正在使用本机.forEach(),并且不会为未初始化的索引调用它的回调。因此,在第一次测试中,永远不会调用_.every()的回调。

编辑 - Array构造函数执行的操作或多或少与:

var a = []; a.length = 10;

当你通过增加它的长度来扩展数组时,新的隐式索引位置不会被初始化。它是不存在属性和存在没有价值的属性之间的基本区别。在这两种情况下,取消引用该属性都会导致undefined。因此:

var o = {};

if (o.something == undefined) // this will be true

然后:

var o = { something: undefined };

if (o.something == undefined) // also true

告诉两种情况之间差异的一种方法是in运算符:

if ('something' in o) // only true in the second case

答案 1 :(得分:2)

使用类初始化程序创建数组时,您将创建一个具有10个可用内存空间的数组,但尚未初始化它们。所以你不会循环任何事情。

现在看一下every的来源:

_.every = _.all = function(obj, iterator, context) {
    iterator || (iterator = _.identity);
    var result = true;
    if (obj == null) return result;       
    if (nativeEvery && obj.every === nativeEvery) return obj.every(iterator, context);
    each(obj, function(value, index, list) {
      if (!(result = result && iterator.call(context, value, index, list))) return breaker;
    });
    return !!result;
};

result设置为true并且由于each没有迭代而返回。这就是你回归true的原因。

如果在您的小提琴中,您尝试在处理程序中添加console.log(m),您将看到控制台中没有日志,因为each迭代0次。