forEach / for ...没有返回值?

时间:2017-04-22 06:13:54

标签: javascript

所以我有点困惑,我正在freeCodeCamp解决挑战。

challenge内容如下

  

一切都是真的

     

检查谓词(第二个参数)是否对集合的所有元素(第一个参数)都是真实的。

它已经解决但我不明白为什么我不得不采取额外措施。我的代码是这样的:

function truthCheck(collection, pre) {
    collection.forEach(function(element) {
        for (key in element) {
            if (!element.hasOwnProperty(pre)) {
                return false;
            } else if (key === pre) {
                if (!Boolean(element[key])) {
                    return false;
                }
            }
        }
    });
    return true;
}

truthCheck([
    {"user": "Tinky-Winky", "sex": "male"},
    {"user": "Dipsy"},
    {"user": "Laa-Laa", "sex": "female"},
    {"user": "Po", "sex": "female"}
], "sex");

所以在这个例子中它应该失败,因为collection中的第二个元素没有sex属性。如果pre参数,或者在这种情况下sex不是真值,您也会收到失败。

当这些被击中时(我们可以通过控制台日志告诉它)但我认为它会突破循环并从truthCheck函数返回.....但它没有不会,它最终会回归真实。

我能够通过定义变量然后将该值设置为false然后在结尾处返回变量来绕过这个。有没有更好的办法?看起来这些回报应该突破truthCheck函数?我错过了什么吗?

5 个答案:

答案 0 :(得分:5)

正如其他答案所解释的那样,这是没有意义的:

collection.forEach(function () {
  // do something
  return false;
});

因为array#forEach根本不关心其worker函数的返回值。它只是为每个数组元素执行worker函数。

您可以使用worker函数设置外部变量:

function truthCheck(collection, pre) {
  var allAreTruthy = true;
  collection.forEach(function (elem) {
    // if this ever flips allAreTruthy to false, it will stay false
    allAreTruthy = allAreTruthy && elem[pre];
  });
  return allAreTruthy;
}

但有更好的方法来表达这一点。

  

检查谓词(第二个参数)是否对集合的所有元素(第一个参数)都是真实的。

可以解释为" 该集合的每个元素在特定键上都具有真实值。"

function truthCheck(collection, pre) {
  return collection.every(function (elem) { return elem[pre]; });
}

可以解释为&#34; 集合中的元素在特定键上具有虚假值(或者完全没有键)。&#34; < / em>的

或者,由于Array#none方法实际上并不存在,&#34;该集合中的某些元素在a处具有假值特别关键。&#34;

function truthCheck(collection, pre) {
  return !collection.some(function (elem) { return !elem[pre]; });
}

使用Array#some的优点是,只要满足它所寻求的条件,它就会停止迭代数组。如果您的阵列有许多元素,这将意味着提高性能。对于短阵列,使用Array#everyArray#forEach并没有多大区别。

以上在语义上等同于

function truthCheck(collection, pre) {
  var i;
  for (i = 0; i < collection.length; i++) {
    if (!collection[i][pre]) return false;
  }
  return true;
}

由于JS对象只是在您访问尚未设置的密钥时返回undefined,因此在此处检查hasOwnProperty是多余的。

答案 1 :(得分:2)

对集合的每个元素执行一个函数。此函数检查元素返回的内容。但是返回的值不会影响外部函数的结果。由于外部函数不依赖于内部函数,因此结果总是如此。

如果你定义一个变量,将它设置为false并在结尾处返回该变量将起作用,但效率很低。让我们想一想以下场景。您找到了一个没有目标键的元素。所以现在你应该回​​来,但你不能。你必须自己完成整个系列。如果没有mess,forEach循环不会让您退出。因此,更好的想法是 for loop 。如果找到你想要的东西,你可以退出退出for循环

更简单的方法是:

function truthCheck(collection, pre) {
    //iterate thrugh your collection
    for (var c in collection){
        //get keys of element as an array and check if pre is in that array
        if( Object.keys(collection[c]).indexOf(pre) == -1){
            // pre was not found
            return false;
        }
    }
    return true;
}

答案 2 :(得分:2)

function truthCheck(collection, pre) {
  return collection.every(function (person) { return !!person[pre]; });
}

答案 3 :(得分:2)

[collection] .for每个javascript都不像普通的循环那样工作。除非你让它抛出异常,否则没有办法过早地结束它。

您期望的行为是您对javascript for循环的期望,但由于forEach为每个循环对象使用回调函数,因此您只退出回调函数而不是forEach。另外值得注意的是,在你的代码中,你有一个for循环,它有一个返回。这个循环中的返回块只打破了这个循环,而不是forEach(我之前提到过,除非另有说明,否则不能过早终止)

正如您所看到的,forEach主要用于迭代所有元素,而不是每个迭代元素的条件检查。

答案 4 :(得分:1)

您无法从ForEach循环返回任何内容。它默认会返回undefined

正如官方文档Array.prototype.forEach() - JavaScript | MDN所说:

  

除了抛出异常之外,没有办法停止或中断forEach()循环。如果你需要这样的行为,forEach()方法是错误的工具,使用普通循环代替。如果要测试谓词的数组元素并需要布尔返回值,则可以使用every()或some()。

所以你可以使用一个非常简单的for..in循环,例如:

for(var c in collection){
    // Do whatever you want
}