1.遍历数组。
2.基于现有的数组元素映射创建新数组。
3.验证数组元素是够匹配指定的条件。
4.查找特定数组元素。
5.聚合数组,基于数组元素计算(例如,计算数组元素之和)
从遍历数组开始
数组遍历:
数组遍历是最常见的操作之一。通常是以如下方式遍历:
console.log('----------------------------------数组遍历--------------------------------------');
const ninjasArray = ['Yagyu', 'Kuma', 'Hattori'];
//报告每个ninja元素的值
for (let i = 0; i < ninjasArray.length; i++) {
console.log(ninjasArray[i]);
}
如上面代码使用for循环查询数组中的每个元素,但是,让我们再仔细检查下这个for循环。
为了遍历数组,我们创建变量i,指向数组的长度(ninjas.length),定义计数器的修改(i++)。有很多这样的操作,这是烦人的缺陷来源,同时导致阅读困难。
console.log('----------------------------------数组遍历--------------------------------------');
const ninjasArray = ['Yagyu', 'Kuma', 'Hattori'];
//报告每个ninja元素的值
//使用forEach遍历数组。
ninjasArray.forEach(ninja=>{
console.log(ninja);
});
提供回调函数(本例中是箭头函数),遍历每一个元素时,立即执行。不需要考虑开始索引、结束条件和计数器。
映射数组
假设有一个数组对象ninja。每个nija具有name和weapon属性,需要从中提取全部的weapon。使用forEach方法。
创建一个新数组,并使用forEach方法遍历ninjas,提取每个元素的weapon属性。
console.log('---------------使用forEach实现数组映射------------------------------');
const ninjas = [
{name: 'Yagyu', weapon : 'shuriken'},
{name: 'Yoshi', weapon : 'katana'},
{name:'Kuma', weapon: 'wakizashi'}
];
//创建一个新数组,并使用forEach方法遍历ninjas,提取每个元素的weapon属性。
const weapons = [];
ninjas.forEach(ninja =>{
weapons.push(ninja.weapon);
});
if (weapons[0] === 'shuriken' && weapons[1] === 'katana' && weapons[2] === 'wakizashi' && weapons.length === 3) {
console.log('The array contains all weapons');
}
上面的方法中,首先创建一个空数组,使用forEach方法遍历ninjas数组,然后,将每个ninja对象的weapon属性添加到weapons数组中。
基于已有数组的 元素创建数组是非常常见的,因此它有一个特殊的名称,数组映射。主要思想是将数组中的每个人元素的属性映射到新数组的元素上。Javascript的map函数可以实现便捷操作。
console.log('---------------------使用map函数实现数组映射-----------------------');
const ninjas = [
{name: 'Yagyu', weapon : 'shuriken'},
{name: 'Yoshi', weapon : 'katana'},
{name:'Kuma', weapon: 'wakizashi'}
];
//内置的map方法接收回调函数作为参数,并对每个元素执行该函数
const weapons = ninjas.map(ninja=>ninja.weapon);
if (weapons[0] === 'shuriken' && weapons[1] === 'katana' && weapons[2] === 'wakizashi' && weapons.length === 3) {
console.log('The array contains all weapons');
}
内置的map方法创建一个全新的数组,然后遍历输入的数组。对输入数组的每一个元素,在新建的数组上,都会基于回调函数的执行结果创建一个对应的元素。
map函数的工作原理如下:
现在,我们知道任何映射数组,接下来让我们看看如何测试数组项是否匹配某些条件。
测试数组元素
处理集合的元素时,常常遇到需要知道数组的全部元素或者部分元素 是否满足条件。Javascript数组具有内置的every和some方法。
console.log('----------------------------使用every和some方法测试数组-------------------------');
const ninjas = [
{name: 'Yagyu', weapon : 'shuriken'},
{name: 'Yoshi'},
{name:'Kuma', weapon: 'wakizashi'}
];
//内置的every方法接收回调函数作为参数,会对每个元素执行该回调函数。如果所有数组元素的回调结果都返回true时,every方法将返回true,否则返回false。
const allNinjasAreNamed = ninjas.every(ninja => "name" in ninja);
const allNinjasAreArmed = ninjas.every(ninja => 'weapon' in ninja);
if (allNinjasAreNamed) {
console.log("Every ninja has a name");
}
if (!allNinjasAreArmed) {
console.log("But not every ninja is armed");
}
//内置的some方法接收回调函数作为参数。只要至少有一项元素的回调结果为true,some方法就返回true,否则返回false
const someNinjasAreArmed = ninjas.some(ninja => "weapon" in ninja);
if (someNinjasAreArmed) {
console.log("But some ninjas are armed!");
}
const allNinjasAreNamed = ninjas.every(ninja => "name" in ninja);
every方法接收回调函数,对集合中的每个ninja对象检查是否含有name属性。当且仅当全部的回调函数都返回true,every方法才会返回true,否则返回false。
every对数组的每个元素执行回调函数,直到返回false。
下图显示every方法的工作原理:
如果回调函数返回false,后续的元素将不再检查
有时,我们只关心数组中的部分元素是否满足某些条件。这时,使用some方法:
const someNinjasAreArmed = ninjas.some(ninja => "weapon" in ninja);
some方法从上数组的第1项开始执行回调函数,直到回调函数返回true.如果有一项元素执行回调函数结束时,返回true,some返回true;否则,some返回false。
some方法的执行机制:
some通过回调函数检查数组中是否至少有一项满足回调函数中指定的条件。
console.log('---------------------------数组查找---------------------------');
//通过数组内置方法find在数组中查找指定元素
//内置的find方法是ES6标准
const ninjas = [
{name: 'Yagyu', weapon : 'shuriken'},
{name: 'Yoshi'},
{name:'Kuma', weapon: 'wakizashi'}
];
//使用find方法查找满足回调函数中指定条件的第一个元素
const ninjaWithWakizashi = ninjas.find(ninja => {
return ninja.weapon === 'wakizashi';
});
if (ninjaWithWakizashi.name === 'Kuma' && ninjaWithWakizashi.weapon === 'wakizashi') {
console.log("Kuma is wielding a wakizashi!");
}
//如果未查找到满足条件的元素,使用find方法返回undefined
const ninjaWithKatana = ninjas.find(ninja => {
return ninja.weapon === 'katana';
});
if (ninjaWithKatana === undefined) {
console.log('We could not find a ninja that wields a katana!');
}
//使用filter方法查找满足条件的多个元素
const armedNinjas = ninjas.filter(ninja => "weapon" in ninja);
if (armedNinjas.length === 2) {
console.log("There are two armed ninjas:");
}
if (armedNinjas[0].name === 'Yagyu' && armedNinjas[1].name === 'Kuma') {
console.log("Yagyu and Kuma");
}
查找满足条件的数组元素很容易:使用内置的find方法,传入回调函数,针对集合中的每个元素调用回调函数,直到查找到目标元素。由回调函数返回true,例如:
const ninjaWithWakizashi = ninjas.find(ninja => {
return ninja.weapon === 'wakizashi';
});
返回undefined,因为没有一项数组的weapon是katana。下图显示find函数的内部工作原理。
如果需要查找满足条件的多个元素,可以使用filter方法,该方法返回满足条件的多个元素的数组。例如:
console.log("----------------------获取数组索引--------------------");
const ninjasArray = ['Yagyu', 'Yoshi', 'Kuma', 'Yoshi'];
if (ninjasArray.indexOf("Yoshi") === 1) {
console.log("Yoshi is at index 1");
}
if (ninjasArray.lastIndexOf("Yoshi")) {
console.log("and at index 3");
}
const yoshiIndex = ninjasArray.findIndex(ninja => ninja === 'Yoshi');
if (yoshiIndex === 1) {
console.log("Yoshi is still at index 1");
}
使用内置的indexOf方法查找特定元素的索引,传入目标函数作为参数:
ninjasArray.indexOf("Yoshi")
有时在数组中具有多个指定的元素(如Yoshi),查找最后一次Yoshi出现的索引。可以使用lastIndex方法:
ninjasArray.lastIndexOf("Yoshi")
最后在大多数情况下,当不具有目标元素的引用时,可以使用findIndex方法查找索引:
const yoshiIndex = ninjasArray.findIndex(ninja => ninja === 'Yoshi');
findIndex方法接收回调函数,并返回第一个回调函数返回true的元素。本质上findIndex与find方法类似,唯一的区别是find方法返回元素本身,而findIndex方法返回元素的索引。
参考书籍<<javascript忍者秘籍>>