2013-10-10 21 views
1

我写了一些像这样的代码: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为“假”,但它返回“真”。 为什么它返回'真'?

然后,我改成这样:

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

它在d返回 '假'。

他们为什么不一样?

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

回答

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次。

+0

我使用'console.log(a)',它打印出[[undefined x 10]'。和'console.log(a [1])',它会打印出'undefined'。这让我感到困惑。如果我可以使用'a [1]'来获得某些东西,为什么我不能迭代它? – shian

+0

http:// perfectionkills。com/how-ecmascript-5-still-does-not-allow-to-subclass-an-array /#special_nature_of_arrays –

+0

谢谢你的链接。 – shian

2

测试这个有与初始化数组构造函数和初始大小的数组,并与undefined条目的显式列表初始化之间的细微差别。前者(数组构造函数)不会创建与索引相对应的属性,而显式初始化则可以。

我怀疑Underscore在可以的时候使用本机.forEach(),并且不会调用它对未初始化索引的回调。因此,在第一个测试中,回调到_.every()永远不会被调用。

编辑 —数组构造器更多的东西或多或少一样:

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