我写了一些这样的代码:
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'为什么他们不同?
中对此进行测试答案 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次。