forEach / for ...不返回值?

msm*_*114 6 javascript

所以我有些困惑,我正在解决freeCodeCamp上的一个挑战。

挑战如下

一切都是真实的

检查谓词(第二个参数)在集合的所有元素(第一个参数)上是否为真。

解决了,但是我不明白为什么我必须采取额外的步骤。我的代码是这样的:

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");
Run Code Online (Sandbox Code Playgroud)

因此在这种情况下,它应该会失败,因为其中的第二个元素collection没有该sex属性。如果pre参数(在这种情况下sex不是真值)也将失败。

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

我可以通过定义一个变量,然后将该值设置为false并在最后返回该变量来规避此问题。有没有更好的办法?似乎这些返回应该突破该truthCheck功能?我想念什么吗?

Blo*_*ost 8

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

作为官方文档,Array.prototype.forEach() - JavaScript | MDN说:

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

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

for(var c in collection){
    // Do whatever you want
} 
Run Code Online (Sandbox Code Playgroud)


Tom*_*lak 6

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

collection.forEach(function () {
  // do something
  return false;
});
Run Code Online (Sandbox Code Playgroud)

因为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;
}
Run Code Online (Sandbox Code Playgroud)

但是有更好的方式表达这一点。

检查谓词(第二个参数)在集合的所有元素(第一个参数)上是否为真。

可以这样解释:“ 集合的每个元素在特定的键上都有真实的价值。”

function truthCheck(collection, pre) {
  return collection.every(function (elem) { return elem[pre]; });
}
Run Code Online (Sandbox Code Playgroud)

可改写为集合的元件具有在特定密钥的falsy值(或者完全丢失,密钥)”。

或者,由于Array#none实际上不存在方法,因此“ 集合中的某些元素在特定键上没有伪造的值”。

function truthCheck(collection, pre) {
  return !collection.some(function (elem) { return !elem[pre]; });
}
Run Code Online (Sandbox Code Playgroud)

使用的优点Array#some是,一旦满足条件,它就会停止迭代数组。如果您的数组包含许多元素,则意味着性能会提高。对于短数组,使用Array#every或并没有太大区别Array#forEach

以上在语义上等同于

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

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


小智 5

[collection].forEach 的 javascript 不像普通循环那样工作。除非你让它抛出异常,否则没有办法提前结束它。

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

如您所见,forEach 主要用于迭代所有元素,而不是对每个迭代元素进行条件检查。