最有用的 JavaScript 数组方法(示例讲解)
如果您是 JavaScript 开发人员并希望提高您的编码能力,那么您应该熟悉最常用的 ES5 和 ES6+ 数组方法。
这些方法使编码变得容易得多,也使您的代码看起来干净且易于理解。
因此,在本文中,我们将探讨一些最流行、应用最广泛的数组方法。那就让我们开始吧。
Array.forEach 方法
该Array.forEach
方法具有以下语法:
Array.forEach(callback(currentValue [, index [, array]])[, thisArg]);
该forEach
方法对数组中的每个元素执行一次提供的函数。
看一下下面的代码:
const months = ['January', 'February', 'March', 'April'];
months.forEach(function(month) {
console.log(month);
});
/* output
January
February
March
April
*/
这是一个Code Pen Demo。
这里,在forEach
循环回调函数内部,数组的每个元素都会自动作为函数的第一个参数传递。
上述示例的等效 for 循环代码如下所示:
const months = ['January', 'February', 'March', 'April'];
for(let i = 0; i < months.length; i++) {
console.log(months[i]);
}
/* output
January
February
March
April
*/
这是一个Code Pen Demo。
您需要记住的是该forEach
方法不返回任何值。
看一下下面的代码:
const months = ['January', 'February', 'March', 'April'];
const returnedValue = months.forEach(function (month) {
return month;
});
console.log('returnedValue: ', returnedValue); // undefined
这是一个Code Pen Demo。
请注意,它
forEach
仅用于循环遍历数组并执行一些处理或日志记录。它不返回任何值,即使你从回调函数显式返回一个值(这意味着返回值undefined
与上例中一样)。
在上述所有示例中,我们仅使用了回调函数的第一个参数。但回调函数还接收两个附加参数,分别是:
- index - 当前正在迭代的元素的索引
- array - 我们正在循环的原始数组
const months = ['January', 'February', 'March', 'April'];
months.forEach(function(month, index, array) {
console.log(month, index, array);
});
/* output
January 0 ["January", "February", "March", "April"]
February 1 ["January", "February", "March", "April"]
March 2 ["January", "February", "March", "April"]
April 3 ["January", "February", "March", "April"]
*/
这是一个Code Pen Demo。
根据要求,您可能会发现使用index
和array
参数很有用。
使用 forEach 代替 for 循环的优点
- 使用
forEach
循环可以使您的代码更短且更容易理解 - 使用
forEach
循环时,我们不需要跟踪数组中有多少个可用元素。因此,它避免了创建额外的计数器变量。 - 使用
forEach
循环使代码易于调试,因为循环遍历数组时不需要额外的变量 forEach
当数组的所有元素都完成迭代后,循环自动停止。
浏览器支持
- 所有现代浏览器和 Internet Explorer (IE) 9 及以上版本
- Microsoft Edge 版本 12 及更高版本
Array.map 方法
数组映射方法是所有数组方法中最有用、应用最广泛的方法。
该Array.map
方法具有以下语法:
Array.map(function callback(currentValue[, index[, array]]) {
// Return element for new_array
}[, thisArg])
该map
方法对数组中的每个元素执行一次提供的函数,并返回一个新的转换数组。
看一下下面的代码:
const months = ['January', 'February', 'March', 'April'];
const transformedArray = months.map(function (month) {
return month.toUpperCase();
});
console.log(transformedArray); // ["JANUARY", "FEBRUARY", "MARCH", "APRIL"]
这是一个Code Pen Demo。
在上面的代码中,在回调函数内部,我们将每个元素转换为大写并返回它。
上述示例的等效 for 循环代码如下所示:
const months = ['January', 'February', 'March', 'April'];
const converted = [];
for(let i = 0; i < months.length; i++) {
converted.push(months[i].toUpperCase());
};
console.log(converted); // ["JANUARY", "FEBRUARY", "MARCH", "APRIL"]
这是一个Code Pen Demo。
使用arraymap
可以避免converted
预先创建单独的数组来存储转换后的元素。因此,它节省了内存空间,并且使用 array 的代码看起来也更简洁map
,如下所示:
const months = ['January', 'February', 'March', 'April'];
console.log(months.map(function (month) {
return month.toUpperCase();
})); // ["JANUARY", "FEBRUARY", "MARCH", "APRIL"]
这是一个Code Pen Demo。
请注意,该map
方法返回一个与原始数组长度完全相同的新数组。
forEach
和方法的区别map
在于forEach
仅用于循环,不返回任何内容。而 则map
返回一个与原始数组长度完全相同的新数组。
另外,请注意,map
不会改变原始数组,而是返回一个新数组。
看一下下面的代码:
const users = [
{
first_name: 'Mike',
last_name: 'Sheridan'
},
{
first_name: 'Tim',
last_name: 'Lee'
},
{
first_name: 'John',
last_name: 'Carte'
}
];
const usersList = users.map(function (user) {
return user.first_name + ' ' + user.last_name;
});
console.log(usersList); // ["Mike Sheridan", "Tim Lee", "John Carte"]
这是一个Code Pen Demo。
在这里,通过使用对象和方法数组map
,我们可以轻松生成一个包含名字和姓氏的数组。
在上面的代码中,我们使用+
运算符来连接两个值。但更常见的是使用 ES6 模板字面量语法,如下所示:
const users = [
{
first_name: 'Mike',
last_name: 'Sheridan'
},
{
first_name: 'Tim',
last_name: 'Lee'
},
{
first_name: 'John',
last_name: 'Carte'
}
];
const usersList = users.map(function (user) {
return `${user.first_name} ${user.last_name}`;
});
console.log(usersList); // ["Mike Sheridan", "Tim Lee", "John Carte"]
这是一个Code Pen Demo。
map
如果您只想从数组中提取特定数据,则数组方法也很有用,如下所示:
const users = [
{
first_name: 'Mike',
last_name: 'Sheridan',
age: 30
},
{
first_name: 'Tim',
last_name: 'Lee',
age: 45
},
{
first_name: 'John',
last_name: 'Carte',
age: 25
}
];
const surnames = users.map(function (user) {
return user.last_name;
});
console.log(surnames); // ["Sheridan", "Lee", "Carte"]
这是一个Code Pen Demo。
在上面的代码中,我们仅提取每个用户的姓氏并将其存储在数组中。
我们甚至可以用来map
生成具有动态内容的数组,如下所示:
const users = [
{
first_name: 'Mike',
location: 'London'
},
{
first_name: 'Tim',
location: 'US'
},
{
first_name: 'John',
location: 'Australia'
}
];
const usersList = users.map(function (user) {
return `${user.first_name} lives in ${user.location}`;
});
console.log(usersList); // ["Mike lives in London", "Tim lives in US", "John lives in Australia"]
这是一个Code Pen Demo。
请注意,在上面的代码中,我们并没有改变原始users
数组。我们创建了一个包含动态内容的新数组,因为map
总是返回一个新数组。
使用 map 方法的优点
- 它有助于快速生成新数组而不改变原始数组
- 它有助于根据每个元素生成具有动态内容的数组
- 它允许我们快速提取数组中的任何元素
- 它生成一个与原始数组长度完全相同的数组
浏览器支持:
- 所有现代浏览器和 Internet Explorer (IE) 9 及以上版本
- Microsoft Edge 版本 12 及更高版本
Array.find 方法
该Array.find
方法具有以下语法:
Array.find(callback(element[, index[, array]])[, thisArg])
该
find
方法返回数组中满足所提供测试条件的value
。first element
该find
方法将回调函数作为第一个参数,并对数组的每个元素执行回调函数。每个数组元素值都作为第一个参数传递给回调函数。
假设我们有这样的员工名单:
const employees = [
{ name: "David Carlson", age: 30 },
{ name: "John Cena", age: 34 },
{ name: "Mike Sheridan", age: 25 },
{ name: "John Carte", age: 50 }
];
我们想要获取员工姓名为 的员工记录John
。在这种情况下,我们可以使用find
如下所示的方法:
const employee = employees.find(function (employee) {
return employee.name.indexOf('John') > -1;
});
console.log(employee); // { name: "John Cena", age: 34 }
这是一个Code Pen Demo。
即使"John Carte"
列表中有 ,该find
方法也会在找到第一个匹配项时停止。因此它不会返回名称为 的对象"John Carte"
。
上述示例的等效 for 循环代码如下所示:
const employees = [
{ name: "David Carlson", age: 30 },
{ name: "John Cena", age: 34 },
{ name: "Mike Sheridan", age: 25 },
{ name: "John Carte", age: 50 }
];
let user;
for(let i = 0; i < employees.length; i++) {
if(employees[i].name.indexOf('John') > -1) {
user = employees[i];
break;
}
}
console.log(user); // { name: "John Cena", age: 34 }
这是一个Code Pen Demo。
如你所见,使用普通的 for 循环会使代码变得更长,更难理解。但使用该find
方法,我们可以用一种更容易理解的方式编写相同的代码。
使用 find 方法的优点
- 它使我们能够快速找到任何元素,而无需编写大量代码
- 一旦找到匹配项,它就会停止循环,因此不需要额外的 break 语句
浏览器支持:
- 除 Internet Explorer (IE) 之外的所有现代浏览器
- Microsoft Edge 版本 12 及更高版本
Array.findIndex 方法
该Array.findIndex
方法具有以下语法:
Array.findIndex(callback(element[, index[, array]])[, thisArg])
该findIndex
方法返回index
数组中第一个元素的satisfies the provided test condition
。否则返回-1
,表示没有元素通过测试。
const employees = [
{ name: 'David Carlson', age: 30 },
{ name: 'John Cena', age: 34 },
{ name: 'Mike Sheridan', age: 25 },
{ name: 'John Carte', age: 50 }
];
const index = employees.findIndex(function (employee) {
return employee.name.indexOf('John') > -1;
});
console.log(index); // 1
这是一个Code Pen Demo。
这里我们得到的输出是1
,这是第一个名为 的对象的索引John
。请注意,索引从零开始。
上述示例的等效 for 循环代码如下所示:
const employees = [
{ name: 'David Carlson', age: 30 },
{ name: 'John Cena', age: 34 },
{ name: 'Mike Sheridan', age: 25 },
{ name: 'John Carte', age: 50 }
];
let index = -1;
for(let i = 0; i < employees.length; i++) {
if(employees[i].name.indexOf('John') > -1) {
index = i;
break;
}
}
console.log(index); // 1
这是一个Code Pen Demo。
使用 findIndex 方法的优点
- 它使我们能够快速找到元素的索引,而无需编写大量代码
- 一旦找到匹配项,它就会停止循环,因此不需要额外的 break 语句
- 我们也可以使用数组方法查找索引
find
,但使用 findIndex 使其变得简单,并避免创建额外的变量来存储索引
浏览器支持:
- 除 Internet Explorer (IE) 之外的所有现代浏览器
- Microsoft Edge 版本 12 及更高版本
Array.filter 方法
该Array.filter
方法具有以下语法:
Array.filter(callback(element[, index[, array]])[, thisArg])
该filter
方法返回a new array
满足所提供测试条件的所有元素。
该filter
方法将回调函数作为第一个参数,并对数组的每个元素执行回调函数。每个数组元素值都作为第一个参数传递给回调函数。
const employees = [
{ name: 'David Carlson', age: 30 },
{ name: 'John Cena', age: 34 },
{ name: 'Mike Sheridan', age: 25 },
{ name: 'John Carte', age: 50 }
];
const employee = employees.filter(function (employee) {
return employee.name.indexOf('John') > -1;
});
console.log(employee); // [ { name: "John Cena", age: 34 }, { name: "John Carte", age: 50 }]
这是一个Code Pen Demo。
从上面的代码可以看出,使用filter
有助于从数组中找到符合指定测试条件的所有元素。
因此,using 函数filter
在找到特定匹配项后不会停止,而是继续检查数组中是否还有其他元素符合条件。然后,它返回数组中所有匹配的元素。
find
和之间的主要区别filter
在于 find 仅返回数组中第一个匹配的元素,而 usingfilter
返回数组中所有匹配的元素。
请注意,该filter
方法始终返回一个数组。如果没有元素通过测试条件,则返回一个空数组。
上述示例的等效 for 循环代码如下所示:
const employees = [
{ name: 'David Carlson', age: 30 },
{ name: 'John Cena', age: 34 },
{ name: 'Mike Sheridan', age: 25 },
{ name: 'John Carte', age: 50 }
];
let filtered = [];
for(let i = 0; i < employees.length; i++) {
if(employees[i].name.indexOf('John') > -1) {
filtered.push(employees[i]);
}
}
console.log(filtered); // [ { name: "John Cena", age: 34 }, { name: "John Carte", age: 50 }]
这是一个Code Pen Demo。
使用过滤方法的优点
- 它使我们能够快速从数组中找到所有匹配的元素
- 即使没有匹配,它也总是返回一个数组,因此避免编写额外的
if
条件 - 它避免了创建额外的变量来存储已过滤元素的需要
浏览器支持:
- 所有现代浏览器和 Internet Explorer (IE) 9 及以上版本
- Microsoft Edge 版本 12 及更高版本
Array.every 方法
该Array.every
方法具有以下语法:
Array.every(callback(element[, index[, array]])[, thisArg])
该every
方法测试数组中的所有元素是否通过提供的测试条件并返回布尔true
值false
。
假设我们有一个数字数组,并且我们想检查数组中的每个元素是否都是正数。我们可以使用此every
方法来实现。
let numbers = [10, -30, 20, 50];
let allPositive = numbers.every(function (number) {
return number > 0;
});
console.log(allPositive); // false
numbers = [10, 30, 20, 50];
allPositive = numbers.every(function (number) {
return number > 0;
});
console.log(allPositive); // true
假设你有一个注册表单,你想在提交表单之前检查所有必填字段是否都已填写。你可以使用every
方法轻松检查每个字段的值。
window.onload = function () {
const form = document.getElementById('registration_form');
form.addEventListener('submit', function (event) {
event.preventDefault();
const fields = ['first_name', 'last_name', 'email', 'city'];
const allFieldsEntered = fields.every(function (fieldId) {
return document.getElementById(fieldId).value.trim() !== '';
});
if (allFieldsEntered) {
console.log('All the fields are entered');
// All the field values are entered, submit the form
} else {
alert('Please, fill out all the field values.');
}
});
};
这是一个Code Pen Demo。
这里,在方法的回调函数中every
,我们检查每个字段值是否不为空并返回一个布尔值。
在上面的代码中,如果对于数组中的所有元素,回调函数都返回一个值,every
则方法返回。true
fields
true
如果回调函数返回数组false
中任何元素的值fields
,则该every
方法将false
作为结果返回。
every
使用此方法的优点
- 它使我们能够快速检查所有元素是否符合特定条件,而无需编写大量代码
浏览器支持:
- 所有现代浏览器和 Internet Explorer (IE) 9 及以上版本
- Microsoft Edge 版本 12 及更高版本
Array.some 方法
该Array.some
方法具有以下语法:
Array.some(callback(element[, index[, array]])[, thisArg]
该some
方法测试数组中是否至少有一个元素通过所提供函数给出的测试条件,并返回布尔值true
或false
值。
true
一旦找到第一个匹配项就返回,false
如果没有匹配项则返回。
假设我们有一个数字数组,并且我们想检查该数组是否至少包含一个正元素。我们可以使用此some
方法来实现。
let numbers = [-30, 40, 20, 50];
let containsPositive = numbers.some(function (number) {
return number > 0;
});
console.log(containsPositive); // true
numbers = [-10, -30, -20, -50];
containsPositive = numbers.every(function (number) {
return number > 0;
});
console.log(containsPositive); // false
该方法有一些有用的使用场景some
。
Some
方法示例1:
假设我们有一个员工列表,我们想检查某个员工是否存在于该数组中。如果找到了,我们还想获取该员工的索引位置。
因此,我们不必单独使用find
和findIndex
方法,而是可以使用some
方法来同时完成这两项操作。
const employees = [
{ name: 'David Carlson', age: 30 },
{ name: 'John Cena', age: 34 },
{ name: 'Mike Sheridon', age: 25 },
{ name: 'John Carte', age: 50 }
];
let indexValue = -1;
const employee = employees.some(function (employee, index) {
const isFound = employee.name.indexOf('John') > -1;
if (isFound) {
indexValue = index;
}
return isFound;
});
console.log(employee, indexValue); // true 1
这是一个Code Pen Demo。
Some
方法示例2:
数组的forEach
、map
和filter
方法会从头到尾运行,直到处理完所有元素。一旦找到特定元素,就无法停止或跳出循环。
在这种情况下,我们可以使用数组some
方法。map
、forEach
和some
方法在回调函数中采用相同的参数:
- 第一个参数是实际值
- 第二个参数是索引
- 第三个参数是原始数组
一旦找到特定的匹配,该some
方法就会停止循环遍历数组,如上面的示例 1 所示。
使用 some 方法的优点
- 它使我们能够快速检查某些元素是否符合某些条件,而无需编写大量代码
- 它允许我们快速跳出循环,这是上面提到的其他循环方法无法实现的
浏览器支持:
- 所有现代浏览器和 Internet Explorer (IE) 9 及以上版本
- Microsoft Edge 版本 12 及更高版本
Array.reduce 方法
该Array.reduce
方法具有以下语法:
Array.reduce(callback(accumulator, currentValue[, index[, array]])[, initialValue])
该方法对数组的每个元素reduce
执行一个函数(您提供的),从而产生单个输出值。reducer
请注意,该方法的输出
reduce
始终是一个值。它可以是对象、数字、字符串、数组等等。这取决于您希望该reduce
方法的输出生成什么,但它始终是一个值。
假设你想求数组中所有数字的总和,你可以使用reduce
该方法。
const numbers = [1, 2, 3, 4, 5];
const sum = numbers.reduce(function(accumulator, number) {
return accumulator + number;
}, 0);
console.log(sum); // 15
这是一个Code Pen Demo。
该reduce
方法接受一个回调函数,该函数接收、 和accumulator
作为number
值。在上面的代码中,我们只使用了和。index
array
accumulator
number
将accumulator
包含用于数组的初始值。initialValue
决定方法返回数据的返回类型reduce
。
这number
是回调函数的第二个参数,它将在循环的每次迭代期间包含数组元素。
在上面的代码中,我们为提供了0
作为。因此,回调函数第一次执行时,将是,我们返回的值是。initialValue
accumulator
accumulator + number
0 + 1 = 1
1
回调函数下次运行时accumulator + number
将是1 + 2 = 3
(1
这里是上次迭代中返回的前一个值,2
是数组中的下一个元素)。
然后,下次回调函数运行时,accumulator + number
将会3 + 3 = 6
(这里的第一个3
是上次迭代中返回的前一个值,下一个3
是数组中的下一个元素)并且它将以这种方式继续,直到数字数组中的所有元素都未被迭代。
因此它将accumulator
像静态变量一样保留上次操作的值。
在上面的代码中,initialValue
of0
不是必需的,因为数组的所有元素都是整数。
因此下面的代码也将起作用:
const numbers = [1, 2, 3, 4, 5];
const sum = numbers.reduce(function (accumulator, number) {
return accumulator + number;
});
console.log(sum); // 15
这是一个Code Pen Demo。
这里,accumulator
将包含数组的第一个元素,number
并将包含数组的下一个元素(1 + 2 = 3
在第一次迭代期间,然后3 + 3 = 6
在下一次迭代期间,依此类推)。
但指定总是好的,initialValue
因为accumulator
它可以轻松理解方法的返回类型reduce
并获取正确的数据类型。
看一下下面的代码:
const numbers = [1, 2, 3, 4, 5];
const doublesSum = numbers.reduce(function (accumulator, number) {
return accumulator + number * 2;
}, 10);
console.log(doublesSum); // 40
这是一个Code Pen Demo。
在这里,我们将数组的每个元素乘以 2。我们initialValue
为累加器提供了 10,因此10
将添加到总和的最终结果中,如下所示:
[1 * 2, 2 * 2, 3 * 2, 4 * 2, 5 * 2] = [2, 4, 6, 8, 10] = 30 + 10 = 40
假设你有一个包含 x 和 y 坐标的对象数组,并且你想获取 x 坐标的总和。你可以使用该reduce
方法。
const coordinates = [
{ x: 1, y: 2 },
{ x: 2, y: 3 },
{ x: 3, y: 4 }
];
const sum = coordinates.reduce(function (accumulator, currentValue) {
return accumulator + currentValue.x;
}, 0);
console.log(sum); // 6
这是一个Code Pen Demo。
使用 reduce 方法的优点
- 使用
reduce
允许我们基于数组生成任何类型的简单或复杂数据 - 它记住先前从循环返回的数据,因此可以帮助我们避免创建全局变量来存储先前的值
浏览器支持:
- 所有现代浏览器和 Internet Explorer (IE) 9 及以上版本
- Microsoft Edge 版本 12 及更高版本
感谢阅读!
想要详细了解所有 ES6+ 功能,包括 let 和 const、承诺、各种承诺方法、数组和对象解构、箭头函数、async/await、导入和导出等等?
看看我的《精通现代 JavaScript》这本书。这本书涵盖了学习 React 的所有先决条件,并能帮助你更好地掌握 JavaScript 和 React。
另外,请查看我的免费React Router 简介课程,从头开始学习 React Router。
想要定期了解有关 JavaScript、React 和 Node.js 的最新内容吗?请在 LinkedIn 上关注我。
鏂囩珷鏉ユ簮锛�https://dev.to/myogeshchavan97/the-most-useful-javascript-array-methods-explained-with-examples-1c54