下划线.js every() 与未定义

underscore.js every() with undefined

本文关键字:未定义 js every 下划线      更新时间:2023-09-26

我写了一些这样的代码:

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

我希望 b 是"假的",但它返回"真"。为什么它返回"true"?

然后,我改成这样:

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

它在 D 中返回"假"。

为什么它们不同?

您可以在 http://jsfiddle.net/3qj4B/3/中对此进行测试

当您使用类初始值设定项创建数组时,您正在创建一个具有 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 次。

使用

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

我怀疑 Underscore 在可能的情况下使用本机.forEach(),并且不会对未初始化的索引调用其回调。因此,在第一个测试中,根本不会调用对_.every()的回调。

edit — 数组构造函数执行的操作或多或少与以下内容相同:

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