我知道map会返回一个新数组,而forEach不返回任何内容(文档说它返回undefined
)。
例如,如果我有这样的代码:
let test;
values.forEach((value, idx) => {
if (someNumber >= value) {
test = value;
}
});
我只是检查someNumber
是否大于某个值,然后设置test = value
。我应该在这里使用另一种数组方法吗?
或者可以使用.forEach
答案 0 :(得分:3)
您的示例没有意义,因为它找到小于或等于value
的 last someNumber
,重复分配给test
变量如果找到多个。因此,您的代码并不能真正表达您的意图,因为其他开发人员可能会对您要实现的目标感到困惑。事实上,由于这种模糊性,这里的其他答案对你的目标有不同的看法。你甚至说:
如果数字大于或等于数组中任何索引的值,则停止并将test设置为等于该值
但是你的代码并没有停在第一个值!它会持续遍历整个数组,test
中的结果将是 last 值,而不是 first 值。
通常,使循环引用外部变量并不是表达意图的最佳方式。这使读者更难理解你在做什么。如果您使用的函数返回一个值,以便明确指定变量,那就更好了。
以下是给您的指南:
<强> forEach 强>
如果要迭代所有值以便对每个值执行某些操作,请使用此选项。如果要创建新的输出值,请不要使用此选项 - 但如果需要修改现有项目或在forEach
没有逻辑输出值的每个项目上运行方法,请使用它。 array.forEach at MDN说:
除了抛出异常之外,没有办法停止或中断forEach()循环。如果你需要这样的行为,forEach()方法是错误的工具,而是使用普通循环。如果要测试谓词的数组元素并需要布尔返回值,则可以使用every()或some()。如果可用,新方法find()或findIndex()也可用于在真正的谓词上提前终止。
<强> find 强>
当你想要找到某个东西的第一个实例时使用它,然后停止。您所说的让它听起来像你想要的那样:
let testResult = values.find(value => value <= someNumber);
这远远优于在lambda或循环内设置test
值。我还认为,由于我们倾向于考虑lambdas的方式,扭转不平等和变量更好。
<强> some 强>
这些只会给你一个布尔值,因此你必须稍微滥用它们来获得输出值。它将遍历数组,直到条件为真或遍历完成,但你必须做一些有点hacky才能获得任何数组值。相反,使用上面的find
,它用于输出找到的值而不是简单的true / false,无论条件是否被数组中的任何元素满足。
<强> every 强>
这类似于some
,因为它返回Boolean
,但正如您所期望的那样,只有当数组中的所有项都满足条件时才会出现。它将遍历数组,直到条件为false或遍历完成。同样,不要通过丢弃布尔结果并将变量设置为值来滥用它。如果您想对数组中的每个项执行某些操作并返回单个值,那么您可能希望使用reduce
。另请注意,!arr.every(lambdacondition)
与arr.some(!lambdacondition)
相同。
<强> reduce 强>
实际编写代码的方式 - 查找与条件匹配的最后一个值 - 自然适用于reduce
:
let testResult = values.reduce(
(recent, value) => {
if (value <= someNumber) {
recent = value;
}
return recent;
},
undefined
);
这与查找示例代码的最后一个值相同。
<强> map 强>
map
用于将数组的每个元素转换为相同长度的新数组。如果您对C#有任何经验,那就像Linq-to-objects .Select
方法一样。例如:
let inputs = [ 1, 2, 3, 4];
let doubleInputs = inputs.map(value => value * 2);
// result: [ 2, 4, 6, 8]
新要求
鉴于您在有序数组中找到相邻值的新描述,在这些数组中可以找到某个值,请考虑以下代码:
let sortedBoundaries = [ 10, 20, 30, 40, 50 ];
let inputValue = 37;
let interval = sortedBoundaries
.map((value, index) => ({ prev: value, next: sortedBoundaries[index + 1] }))
.find(pair => pair.prev < inputValue && inputValue <= pair.next);
// result: { prev: 20, next: 30 }
你可以改进这一点,以便在数字上使用&gt;也将找到50或&lt; = 10(例如,{ prev: undefined, next: 10 }
)。
最后的笔记
通过使用这种返回值而不是修改外部变量的编码方式,您不仅可以更好地向其他开发人员传达您的意图,还可以使用const
代替let
之后不会重新分配变量。
我鼓励您浏览MDN上各种Array
原型函数的文档 - 这样做可以帮助您解决这些问题。请注意,我列出的每个方法都是MDN文档的链接。
答案 1 :(得分:2)
我建议您使用Array#some
,而不是Array#forEach
。
Array#forEach
保持迭代数组,即使已满足给定条件也是如此。
Array#some
在满足给定条件时停止迭代。
其中一个优点是与性能相关,另一个优势 - 取决于您的目的 - Array#forEach
会在每个传递的条件下覆盖结果,Array#some
分配第一个找到的值并停止迭代。 / p>
let test,
values = [4,5,6,7],
someNumber = 5;
values.some((value, idx) => {
if (someNumber >= value) {
test = value;
return test;
}
});
console.log(test);
答案 2 :(得分:2)
另一种选择是使用Array.some()
方法。
let test;
const someNumber = 10;
[1, 5, 10, 15].some(function (value) {
if (value > someNumber) {
return test = value
}
})
.some()
方法优于原始解决方案的一个优点是优化,因为一旦满足条件,它将return
。
答案 3 :(得分:0)
对象怎么样? 你可以搜索for-of