曾经发生过您想通过遍历数组对数组进行一些操作并且不知道应该使用哪个内置函数所以您只是用谷歌搜索您的问题或最近使用 Chat-GPT 并粘贴出现的任何函数或者在一天结束的时候自己写一个 for 循环。
现在也许编写 for 循环会让人感到安慰,因为您从未完全理解这些内置函数的原因和时间。因此,在此博客中,我将尝试让您了解我所了解的有关这些功能的所有内容。
让我们从地图开始
地图
所以 Map 是 JavaScript 中的一个内置函数,用于迭代/循环预定义数组并转换其元素并返回一个新数组,因此它不会在此过程中改变或对原始数组进行任何更改。
它需要一个回调函数,其中包含将元素添加到我们的新数组的逻辑。
现在在回调函数中,您可以编写定义将返回到新数组的内容的逻辑。
该值从回调函数返回,然后附加到新数组中要迭代的元素的位置。
迭代结束后,map 将返回新数组。
Map 返回的新数组将始终与原始数组的长度完全相同。
它的应用是改变或转换原始数组的值。
现在,当我说它用于更改或转换原始数组的值时,并不意味着返回的数组必须与原始数组类似,您甚至可以返回一个数组,其中每个元素的值仅为 1。
听起来很傻吧?但这就是 Map 所做的,新数组只是意味着与原始数组的长度相同,内容由您为正在迭代的每个元素的位置选择。
例如假设我们有一个这样的数组
let fruits = ['apple', 'banana', 'apple', 'watermelon', 'apple']
现在我想制作一个数组,其中“苹果”由 1 表示,所有其他水果由 0 表示。
让我们看看我们如何做到这一点
所以让我们先看看地图的基本语法
array.map(callback(CurrentValue, index));
让我们分解一下
所以我们用数组开始语句,我们需要在数组上进行处理,然后我们在 map 函数中传递了一个回调函数,现在这个回调函数有 3 个参数
CurrentValue - 它是我们原始数组中的值,每次迭代都会发送到回调函数中。我们如何使用 for 循环,我们像 fruits[i] 一样迭代循环的每个元素,所以在这里你可以直接获得你过去使用 fruits[i] 获得的值。
索引 - 现在它几乎是不言自明的,它是将在其上完成处理的当前元素的索引。它是一个可选参数。
现在回到我们的问题
现在我们理解了语法,让我们看看如何获得我们想要的数组。
所以你记得这取决于我们要在新数组中被迭代的元素的位置发送什么。
所以在这个问题中我们可以做的是在回调函数中返回值,我们可以编写一个 if 条件,如果 CurrentValue 等于 apple 则返回 1,否则返回 0。
let fruits = ['apple', 'banana', 'apple', 'watermelon', 'apple']
let new_fruits = fruits.map((elem)=>{
if(elem === 'apple'){
return 1
}
else{
return 0
}
})
console.log(new_fruits) //[ 1, 0, 1, 0, 1 ]
很简单吧?我们只是使用我们的逻辑返回一个新数组。
我们的 Map 函数在每次迭代时收集值并将其分配给新数组中的相应位置。
现在我们明白了 map 根据我们返回的内容将值放入新数组中,对吗?如果我不退还任何东西怎么办?
就像我们上面的例子,如果元素是’apple’我不返回任何东西
let fruits = ['apple', 'banana', 'apple', 'watermelon', 'apple']
let new_fruits = fruits.map((elem)=>{
if(elem !== 'apple'){
return 0
}
})
console.log(new_fruits) //[ undefined, 0, undefined, 0, undefined ]
正如您所看到的,它返回未定义,但为什么呢?在 JavaScript 中,如果函数没有明确的 return 语句或者 return 语句为空,则函数隐式返回 undefined。
当您没有从传递给 map 的回调函数中返回任何内容时,map 函数的每次迭代仍会为数组的每个元素执行回调。但是,由于没有显式返回值,该函数的默认行为是隐式返回 undefined。
在我们转到过滤器之前让我们再看一个例子
假设我有一个包含学生姓名和 ID 的学生对象,现在我想创建一个仅包含学生姓名的数组。
好吧,我认为它很容易做到,既然我们知道地图是如何工作的。
const students = [
{ id: 1, name: "Alice" },
{ id: 2, name: "Bob" },
{ id: 3, name: "Charlie" }
];
const studentNames = students.map(function(student) {
return student.name;
});
console.log(studentNames); // Output: ["Alice", "Bob", "Charlie"]
在这种情况下不需要任何条件,因为我们只想从每个对象返回名称。
为什么好用Map?
Well 允许您编写简洁和声明性的代码。它消除了使用 for 或 while 等循环进行手动迭代的需要。
当它返回一个新数组时,它会处理不可变性,因此无论您对新数组做什么,原始数组都不会受到影响。
可用于通过返回新数组来创建数组的浅表副本。
很有用吧?现在让我们继续过滤
筛选
那么Filter函数也是遍历一个数组,返回一个新的数组,那么它和map有什么不同呢?Well map 可以将原始数组的每个值进行转换,并返回与原始数组长度相同的新数组。
过滤器不具备这两个功能。
顾名思义就是用来过滤掉一个数组的。因此,如果您传递一个数组,它将返回一个不包含您决定的某些元素的数组。
它的语法与 Map 相同,只是将 map 替换为 filter
现在它如何删除元素?所以在回调函数中你可以写一个逻辑或者任何你想做的事情但是你只能返回布尔值。这决定了是否将 currentValue 发送到新数组。因此,如果您返回 true,它将包含在新数组中,否则不会。
例如,如果您有一个由奇数和偶数组成的数组,并且您想返回一个只有偶数的数组,那么:-
const Array = [1, 2, 3, 4, 5, 6];
const NewArray = Array.filter((element)=>{
if(element%2 === 0){
return true
}
})
console.log(NewArray) //[ 2, 4, 6 ]
正如您在这段代码中看到的,如果元素是奇数,我没有指定任何返回值,但仍然没有问题,这是因为如果未指定布尔值,过滤器函数默认将其视为 false。
现在我们知道 filter 的回调函数只返回布尔值,但我很好奇如果在上面的例子中我返回了 5,当数字是偶数时会发生什么。
结果是一样的,我得到了偶数的数组,但是为什么呢?Filter 的回调函数应该只返回布尔值,对吗?所以是的,它仍然返回布尔值。
如何?
所以在 JavaScript 中有一个叫做truthyand falsyvalues 的东西。
在 JavaScript 中,真值是在布尔上下文中计算时被视为“真”的值。它们是非布尔值,被视为真值。
JavaScript 中有许多真值,如非空字符串、数字、数组、对象、非空值、非未定义值等。
也有真实值的简单例子
if ("Hello") {
console.log("This will be executed.");
}
这里 Hello 是一个非空字符串,因此它是一个真值,因此为真,因此条件为真。
现在建议大家只有在想要得到一个过滤后的新数组的时候才使用Filter,如果只是循环遍历,会是不必要的迭代,当数组很大时会出问题,不仅会出问题,而且也具有误导性,因为如果您使用 filter 只是迭代其他人会在查看您的代码时感到困惑。
这总结了过滤器的概念。
对于每个
因此,与 Map 和 Filter 相比,这个循环很简单,因为它没有像它们那样提供任何独有的功能。它不返回任何新数组,它是原始数组的转换或过滤版本,基本上它不返回任何东西。它基本上是一种编写 for 循环的简洁方法,它与简单的 for 循环没有任何不同。就像您在 for 循环范围之外创建一个新数组,然后在循环运行时将新元素推送到数组中一样,您在 Foreach 循环中也是如此。
for 循环和 ForEach 循环之间的一个区别是,您不能像使用 For 循环那样停止 ForEach 循环,也不能添加语句来break结束循环。这对于我们谈到的所有三个功能都是一样的。毫无疑问,它会遍历每个元素。
这是一个简单的问题,先使用 for 循环然后使用 ForEach 解决。
使用 For 循环
var numbers = [1, 2, 3, 4, 5];
var sum = 0;
for (var i = 0; i < numbers.length; i++) {
sum += numbers[i];
}
console.log(sum); // Output: 15
使用 Foreach 循环
var numbers = [1, 2, 3, 4, 5];
var sum = 0;
numbers.forEach(function(number) {
sum += number;
});
console.log(sum); // Output: 15
三个函数就到此结束了,希望你现在明白了😁