所以我有点困惑,我正在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
函数?我错过了什么吗?
答案 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#every
或Array#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
}