3

我注意到一种奇怪的行为,至少是我不明白的一种,同时在每个循环的下划线内返回值。我的代码如下,它基本上测试一个元素是否已经存在于基于其 id 的数组中,如下所示:

var elements = [{id: "1", name : "foo"},{id : "3", name: "bar"}];

element_exists = function(key, val){
    _.each(elements,function(element){
        console.log(element[key], val);
        if(element[key] == val){
            console.log("element exists");
                return true;
        }
   });
   return false;
};

console.log("true : ", element_exists("id", "1"));
console.log("false : ", element_exists("id", "2"));

我在控制台中得到以下日志:

1 1
element exists
3 1
true : false
1 2
3 2
false : false

我的问题是为什么函数不会为第一个元素返回 true ?

4

3 回答 3

6

@ltbesh你弄错了!该函数确实返回值并停止。它只继续为输入中的剩余元素执行迭代器函数。

您将循环语句与_.each方法混淆了。

_.each方法的第二个参数是一个迭代器函数。它基本上是一个针对数组的每个元素执行的函数。因此,如果您return在迭代器函数中编写语句,它只会终止该特定函数调用。继续为数组中的剩余元素调用该函数。

更新


UnderscoreJS 解决方案

您需要使用的是_.find_.some下划线方法。(好吧,现在是 2020 年了,是时候放弃使用下划线和 lodash 来获得 ES6 提供的开箱即用功能了)。但是,由于问题是关于 underscoreJS,我将首先提供一个使用下划线的解决方案。

var elements = [{id: "1", name : "foo"},{id : "3", name: "bar"}];

element_exists = function(key, val){
    return _.find(elements,function(element){
        return element[key] === val;
   });
};

console.log("true : ", element_exists("id", "1"));
console.log("false : ", element_exists("id", "2"));
<script src="https://underscorejs.org/underscore-min.js"></script>

基于 ES6 的解决方案

现在,为了展示在 ES6 中完成相同功能而无需任何外部库是多么简洁,这里是 ES6 版本:

var elements = [{id: "1", name : "foo"},{id : "3", name: "bar"}];

element_exists = (key, val) => (
    elements.find(element => element[key] === val)
)

console.log("true : ", element_exists("id", "1"));
console.log("false : ", element_exists("id", "2"));

PS:如果您只想检查元素是否存在并且不希望它被您的element_exists方法返回,请从 using 切换findsome

于 2013-11-06T13:09:41.940 回答
1

发生这种情况是因为您总是从函数返回 false。

如果您想继续使用该each()功能,请重写此内容。

var elements = [{id: "1", name : "foo"},{id : "3", name: "bar"}];

element_exists = function(key, val){
  var someFlag = false;  
  _.each(elements, function(element){
        console.log(element[key] +" - "+ val);
        if(element[key] == val){
            console.log("element exists");
            someFlag = true;
        }
   });
   return someFlag;
};

console.log("should be true : " + element_exists("id", "1"));
console.log("should be false : " +element_exists("id", "2"));
于 2013-10-25T07:05:09.093 回答
1

有点晚了,但接受的答案没有提供解决方案,所以:

Underscore 建议使用函数_.find,它遍历一个值列表并返回第一个通过真值测试的值,undefined否则返回。

这样你就可以跳出循环。但是,由于返回值是实际元素而不是布尔值,因此您可以在调用函数时添加一个包装器以true在函数返回定义值时返回。

_.some也可能更好地适用于您的用例。

资料来源:

http://underscorejs.org/#each

http://underscorejs.org/#find

http://underscorejs.org/#some

于 2016-08-29T17:47:47.947 回答