Javascript - 深入数组循环
萨拉姆和约什!
这周,我想聊聊JavaScript的核心内容。有些东西你无法回避,总是在你编写代码时萦绕在心头,避而不谈根本行不通。那就是数据结构。没错,是数据结构的基础知识,但我们今天只关注一个方面——数组。
你迟早都会接触到数组。它迟早会萦绕在你的脑海中:我应该用什么方法?如何管理数组?数组是如何工作的?
在 JavaScript 世界中,数组实际上是一个对象,可以遍历数组元素,因为索引是按顺序排列的,所以循环会沿着索引序列进行操作。从 0 开始。等等,从 0 开始?
大批
一个对象,以number作为索引。请注意,这是 JavaScript 中数组的工作方式,并不完全适用于其他语言,例如 Python 等。
以数字作为索引,可以从 0 开始按顺序遍历。由于比特从 0 开始,所以数组从 0 而不是 1 开始。因为索引是按顺序排列的,所以可以遍历数组中的每个元素。
有很多方法可以用来遍历数组,每种方法都有其特定的用途,无论是直接修改数组,还是返回一个新数组或一个值。
正常循环
当然,JavaScript 和其他语言一样也有循环,它们是:`if`、`if`for和while`if` do...while。
for(let i = 0; i < 10; i++) {
// This loop will execute 10 times
}
let j = 0;
while (j < 10) {
// Same here
j++;
}
let k = 0;
do {
// Just the same, except the checking happens
// after execution, opposite to `for` and `while` loop
k++;
} while(k < 0);
当然,使用常规的循环方法并没有错。但是,当你处理数组时,问题就出现了。数组有一个优点:每个数组都可以通过访问自身来获取长度array.length。为什么不利用这个信息来进行循环呢?
for对于数组
第一步,有一个for专门用于数组的循环,那就是for...of。
const fruits = ['Durian', 'Rambutan', 'Nangka'];
for(let fruit of fruits) {
console.log(fruit);
}
/* The output should be:
Durian
Rambutan
Nangka
*/
不要混淆,实际上有一个类似的循环,它for...in实际上是针对对象而不是数组的(是的,我知道在 Javascript 中数组也是对象,但它就是这样工作的!)。
const user = { fname: "Atif", lname: "Aiman", nname: "al-Serembani" };
for(let key in user) {
console.log(user[key]);
}
/* The output should be:
Atif
Aiman
al-Serembani
*/
更好的循环——数组方法!
遍历数组固然重要for...of,但还有更酷炫的遍历方式,那就是使用数组方法!数组方法有很多,各有用途。它们是:
forEachmapreduce和reduceRightfilterfind和findIndexsome和everysortflatMap
由于它们是方法,因此其用法与我们之前使用的模式不同,而是与数组本身链接在一起。
我们来逐一了解一下吧?
array.forEach
forEach这就像我们通常的for...of循环一样。它不返回任何值,也没有改变现有的数组。
const fruits = ['Durian', 'Rambutan', 'Nangka'];
fruits.forEach((fruit) => {
console.log(fruit);
}
/* The output should be:
Durian
Rambutan
Nangka
*/
简单解释一下(后面所有数组方法都类似),我们fruits使用 `for` 循环遍历数组forEach,并将fruit指向每个数组元素的指针传递给它。之后,你就可以对每个元素执行任何操作了。
由于forEach没有返回任何值,这意味着下面的示例不起作用。
const result = fruits.forEach((fruit) => { return fruit + ' juice' });
console.log(result); // undefined
而且forEach没有修改现有数组。这意味着值将保持不变。
array.map
array.map它会遍历数组,然后返回一个长度相同但内容已修改的数组。但它不会修改原始数组。
const fruits = ['Durian', 'Rambutan', 'Nangka'];
const juices = fruits.map((fruit) => {
fruit.press();
});
console.log(juices);
// ['Durian juice', 'Rambutan juice', 'Nangka juice'];
正如你所看到的,我想把这些水果榨成果汁,所以我把每个水果都压榨了一遍,之后就得到了各种各样的果汁。嗯,榴莲汁确实很奇怪,但你敢尝试吗?
array.reduce和array.reduceRight
array.reduce它会遍历数组并处理所有元素,最终返回一个值。array.map这与返回目标数组相同长度的数组不同,而且不会改变原始数组。
const fruits = ['Durian', 'Rambutan', 'Nangka'];
const salad = fruits.reduce((product, fruit) => {
return product + fruit.slice();
});
console.log(salad);
// DuRamNa Salad;
我在这里的做法是,把所有能找到的水果都切片,然后和剩下的食材混合在一起,最后把切好的水果拌成沙拉。榴莲沙拉?别想了!
那么,你通常在哪里看到reduce实际应用呢?一个非常基础的现实世界例子就是 sum!
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const sum = numbers.reduce((total, number) => {
return total + number;
});
console.log(sum); // 55
那么,如果反过来呢?不是从 0 开始,而是从最后一个元素开始呢?在这种情况下,我们使用array.reduceRight`!`。写法相同,只是它会从数组的最后一个索引开始。
array.filter
array.filter程序将遍历数组,仅当数组符合条件或返回 true 时才进行过滤。返回的数组将基于过滤后的结果,并且不会改变原始值。
const fruits = ['Durian', 'Rambutan', 'Nangka'];
const bigFruits = fruits.filter((fruit) => {
return fruit.isBig();
});
console.log(bigFruits); // ['Durian', 'Nangka']
我想知道哪个水果最大。所以我检查了每个水果的大小,结果得到了一个包含所有大水果的数组。现在我知道哪个水果最大了,当然,水果之王榴莲也在其中!
array.find和array.findIndex
array.find它会遍历数组,并且只返回第一个符合条件的元素。array.filter这与返回所有符合条件的元素不同。
const fruits = ['Durian', 'Rambutan', 'Nangka'];
const bigFruit = fruits.find((fruit) => {
return fruit.isBig();
});
console.log(bigFruit); // Durian
榴莲是这组水果中第一个个头大的。如果榴莲不存在,那么菠萝蜜就会成为下一个个头大的水果。
那么,如果我不想知道哪种水果大,而是想知道它在数组中的位置呢?那么,这个array.findIndex方法就很适合你!
const fruits = ['Durian', 'Rambutan', 'Nangka'];
const bigFruit = fruits.findIndex((fruit) => {
return fruit.isBig();
});
console.log(bigFruit); // 0
那么,如果我们在数组中找不到任何符合条件的元素会怎样呢?那么,undefined对于 ` \n`,它将返回 `\n`;array.find对于 `\n`,-1它将返回array.findIndex`\n`。
array.some和array.every
array.some它array.every会遍历数组,并检查它是否符合条件。虽然也可以使用array.reduce返回单个值的函数来实现,array.some但函数会在任何一个元素符合条件时返回 true,而array.every函数会在所有元素都符合条件时返回 true。最终,两者都会返回一个布尔值。
const fruits = ['Durian', 'Rambutan', 'Nangka'];
const hasSmallFruit = fruits.some((fruit) => {
return fruit.isSmall();
});
console.log(hasSmallFruit); // true
const everthingBig = fruits.every((fruit) => {
return fruit.isBig();
});
console.log(everythingBig); // false
我想检查一下有没有个头小的水果。因为红毛丹个头小,所以结果会是真。之后,我还想检查一下是不是所有水果都很大。嗯,如果所有水果都很大的话,我可能就需要一辆卡车了!
array.sort
array.sort它会遍历数组,并根据条件进行排序。当然,返回的数组长度不变,只是排列顺序有所改变。
const fruits = ['Durian', 'Rambutan', 'Nangka'];
const sortedFruit = fruits.sort((fruitA, fruitB) => {
if (fruitA > fruitB) return 1;
else if (fruitA < fruitB) return -1;
else return 0;
});
console.log(sortedFruit); // ['Nangka', 'Durian', 'Rambutan']
在这里,我想根据水果的大小对其进行排序。在循环过程中,它会接收两个参数:第一个水果fruitA和第二个水果fruitB。第一个水果和第二个水果可以是任意的,排序函数会处理它们。之后,我会将它们直接比较,看看哪个水果是这片土地上最大的。
如果返回的是正数,则将第一个水果放在最前面;
如果返回的是负数,则将第一个水果放在最后面;
如果返回的是0,则保持原样,因为重新排列它们无关紧要。
因此,现在我知道,即使榴莲是水果之王,但还有更大的水果——菠萝蜜,所以榴莲也不应该感到太优越。
那么,如何实现反向排序呢?只需将正收益改为负收益,就完成了!你就得到了反向排序!
还有一件事。有没有默认的排序方法,这样我就不用手动传递排序函数了?当然可以!它们会按照字符的字典序排序。换句话说,az 会排在最前面,AZ 排在后面。数字也一样,它们都会被视为字符串。排序[1, 2, 5, 10, 15, 20, 50]结果为[1, 10, 15, 2, 20, 5, 50]……
const fruits = ['Durian', 'Rambutan', 'Nangka'];
const sortedFruit = fruits.sort();
console.log(sortedFruit); // ['Durian', 'Nangka', 'Rambutan']
array.flatMap
其实它的工作方式和以前一样array.map,只不过我们现在处理的是嵌套数组。
实际上,有一个数组方法叫做 `setArray()` array.flat,它可以将嵌套数组(或非一维数组)及其所有元素扁平化,转换为仅包含一维元素的数组。它不是循环方法,所以我没有把它列出来。
array.flat结合和的力量array.map,结果是array.flatMap,它返回扁平化数组的新长度。
差不多就是这样了!
这些是可以在 JavaScript 中使用的数组方法。它符合 ES2020 语法,所以您可以放心使用。
请注意,所有循环数组方法都不会修改原始数组,所以您不必担心。它们会向各自的返回方法返回一个新值。
太棒了,现在你掌握了数组循环方法的基础知识!当然,前提是数据结构很简单!如果是嵌套数组或者数组中包含对象呢?只有实践才能揭晓答案。即便如此,你仍然需要用到这些方法。你的循环能有多复杂呢?
好了各位!本周就到这里,敬请期待!下次再见,祝大家平安!
文章来源:https://dev.to/alserembani/javascript-into-the-loop-of-arrays-51ep







