1

我写了一些这样的代码:

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/中对此进行测试

4

2 回答 2

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

于 2013-10-10T14:14:07.760 回答
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
于 2013-10-10T14:13:09.203 回答