前言
通过梳理数组 API 的方式,归纳整理,你会发现js的数据方法并没有很难记住,一起来学习吧~
提醒一下大家,不要看到目录里那么多的数组方法就望而却步,一定要先看完数组原生方法梳理
,了解数组到底有哪些方法,然后再逐个学习,这样你就会突然发现,其实数组也没多少方法嘛 ~ 都是能用到的
文章目录
- 前言
- 数组原生方法梳理
- `Array.isArray()` 数组判断
- `concat()` 数组合并
- `join()` 数组和字符串的转换
- 数组尾部操作
- 🍅 `pop()`
- 🍅 `push()`
- 数组首部操作
- 🍅 `shift()`
- 🍅 `unshift()`
- 数组重排序
- 🍅 `reverse()` ` [rɪˈvɜrs]`
- 🍅 `sort()`
- `slice()` `[slaɪs] ` 数组截取 ✨
- `splice()` `[splaɪs]` 数组删除、替换或插入
- 数组查找指定元素
- 🍅 `indexOf()`
- 🍅 `lastIndexOf()`
- 🍅 `includes()`
- 🍅 `find()`
- 🍅 `findIndex()`
- 数组迭代
- 🍅 `forEach()`
- 🍅 `map()`
- 🍅 `filter()`
- 🍅 `every()`
- 🍅 `some()`
- `reduce()` 数组归并
- `flat()` 数组扁平化
数组原生方法梳理
🔶 数组 判断方法:Array.isArray()
🔶 数组 合并的方法:concat()
,返回的是拼接好的数组,不影响原数组。
🔶 数组和字符串的转换方法:toString()
、join()
, 其中 join()
方法可以指定转换为字符串时的分隔符。
🔶 数组 尾部操作的方法: pop()
和 push()
,push()
方法可以传入多个参数。
🔶 数组 首部操作的方法: shift()
和 unshift()
;
🔶 数组 重排序的方法: reverse()
和 sort()
;sort()
方法可以传入一个函数来进行比较,传入前后两个值,如果返回值为正数,则b 会被排列到 a 之前;如果返回值为负数, a 会被排列到 b 之前。
🔶 数组 截取办法: slice()
,用于截取数组中的一部分,返回一个新的数组对象,不影响原数组。arr.slice(begin, end)
,slice
会提取原数组中索引从 begin
到 end
的所有元素(包含 begin
,但不包含 end
)。 注意 ❗ ❗ ❗ slice()
方法是浅拷贝,具体在下文做解释。
🔶 数组 删除、替换或插入方法: splice()
,通过删除或替换现有元素或者原地添加新的元素来修改数组,并以数组形式返回被修改的内容 (注意不是整个数组)
。此方法会改变原数组。
🔶 数组 元素查找方法:indexOf()
、includes()
、find()
和 findIndex()
🔶 数组 迭代方法:forEach()
、map()
、filter()
、every()
和 some()
🔶 数组 归并方法: reduce()
🔶 数组 扁平化方法: flat()
Array.isArray()
数组判断
Array.isArray()
用于确定传递的值是否是一个 Array。
Array.isArray([1, 2, 3]);
// true
Array.isArray({foo: 123});
// false
Array.isArray("foobar");
// false
Array.isArray(undefined);
// false
🔶 instanceof 和 isArray
当检测Array实例时, Array.isArray
优于 instanceof
,因为Array.isArray
能检测iframes
.
var iframe = document.createElement('iframe');
document.body.appendChild(iframe);
xArray = window.frames[window.frames.length-1].Array;
var arr = new xArray(1,2,3); // [1,2,3]
// Correctly checking for Array
Array.isArray(arr); // true
// Considered harmful, because doesn't work though iframes
arr instanceof Array; // false
concat()
数组合并
concat()
方法用于合并两个或多个数组。此方法不会更改现有数组,而是返回一个新数组。
合并两个数组:
const array1 = ['a', 'b', 'c'];
const array2 = ['d', 'e', 'f'];
const array3 = array1.concat(array2);
console.log(array3);// Array ["a", "b", "c", "d", "e", "f"]
合并三个数组
以下代码将三个数组合并为一个新数组:
var num1 = [1, 2, 3],
num2 = [4, 5, 6],
num3 = [7, 8, 9];
var nums = num1.concat(num2, num3);
console.log(nums);// [1, 2, 3, 4, 5, 6, 7, 8, 9]
join()
数组和字符串的转换
join()
方法 将数组转换为字符串,并指定所有元素之间的分隔符。
const elements = ['Fire', 'Air', 'Water'];
console.log(elements.join()); // "Fire,Air,Water"
console.log(elements.join('')); // "FireAirWater"
console.log(elements.join('-')); // "Fire-Air-Water"
数组尾部操作
🍅 pop()
pop()
方法 删除数组最后一个元素,并返回该元素的值。此方法更改数组的长度。
const plants = ['broccoli', 'cauliflower', 'cabbage', 'kale', 'tomato'];
console.log(plants.pop()); // "tomato"
console.log(plants); // Array ["broccoli", "cauliflower", "cabbage", "kale"]
plants.pop();
console.log(plants); //Array ["broccoli", "cauliflower", "cabbage"]
🍅 push()
push()
方法 将一个或多个元素添加到数组的末尾,并返回该数组的新长度。
const animals = ['pigs', 'goats', 'sheep'];
const count = animals.push('cows');
console.log(count); // 4
console.log(animals); // Array ["pigs", "goats", "sheep", "cows"]
animals.push('chickens', 'cats', 'dogs');
console.log(animals); // Array ["pigs", "goats", "sheep", "cows", "chickens", "cats", "dogs"]
数组首部操作
🍅 shift()
shift()
方法 删除数组第一个元素,并返回该元素的值。此方法更改数组的长度。
const array1 = [1, 2, 3];
const firstElement = array1.shift();
console.log(array1); // Array [2, 3]
console.log(firstElement); // 1
🍅 unshift()
unshift()
方法将一个或多个元素添加到数组的开头,并返回该数组的新长度(该方法修改原有数组)。
const array1 = [1, 2, 3];
console.log(array1.unshift(4, 5)); // 5
console.log(array1); // Array [4, 5, 1, 2, 3]
数组重排序
🍅 reverse()
[rɪˈvɜrs]
reverse()
方法将数组中元素的位置颠倒,并返回该数组。该方法会改变原数组。
let a = [1, 2, 3, 4, 5];
a.reverse();
console.log(a); // (5) [5, 4, 3, 2, 1]
🍅 sort()
sort()
方法可以传入一个函数对数组的元素进行排序,传入a,b前后两个值,如果返回值为正数,则b 会被排列到 a 之前;如果返回值为负数, a 会被排列到 b 之前。
如果没有指明 排序算法,那么元素会按照转换为的字符串的诸个字符的Unicode位点进行排序。例如 “Banana” 会被排列到 “cherry” 之前。当数字按由小到大排序时,9 出现在 80 之前,但因为(没有指明 compareFunction),比较的数字会先被转换为字符串,所以在Unicode顺序上 “80” 要比 “9” 要靠前。
不指明 排序算法的用法:
const months = ['March', 'Jan', 'Feb', 'Dec'];
months.sort();
console.log(months);// Array ["Dec", "Feb", "Jan", "March"]
const array1 = [1, 30, 4, 21, 100000];
array1.sort();
console.log(array1);// Array [1, 100000, 21, 30, 4]
指明 排序算法的用法:
可以用简单的写法比较数字:
var numbers = [4, 2, 5, 1, 3];
numbers.sort(function(a, b) {
return a - b;
});
console.log(numbers); // [1, 2, 3, 4, 5]
也可以写成:
var numbers = [4, 2, 5, 1, 3];
numbers.sort((a, b) => a - b);
console.log(numbers); // [1, 2, 3, 4, 5]
可以按照对象的某个属性排序:
var items = [
{ name: 'Edward', value: 21 },
{ name: 'Sharpe', value: 37 },
{ name: 'And', value: 45 },
{ name: 'The', value: -12 },
{ name: 'Magnetic' },
{ name: 'Zeros', value: 37 }
];
// sort by value
items.sort(function (a, b) {
return (a.value - b.value)
});
console.log(items);// [
{"name": "The","value": -12},
{"name": "Edward","value": 21},
{"name": "Sharpe","value": 37},
{"name": "And","value": 45},
{"name": "Magnetic"},
{"name": "Zeros","value": 37}
]
compareFunction(a, b)
必须总是对相同的输入返回相同的比较结果,否则排序的结果将是不确定的,比如上面比较函数的输出结果,对value属性的排序结果是不确定的。
所以,如果我们按照对象的某个属性排序,需要确保对象的属性值存在:
var items = [
{name: 'Edward',value: 21},
{name: 'Sharpe',value: 37},
{name: 'And',value: 45},
{name: 'The',value: -12},
{name: 'Magnetic',value: 100},
{name: 'Zeros',value: 37}
];
// sort by value
items.sort(function (a, b) {
return (b.value - a.value)
// 注意,这次把 a.value - b.value 改为了b.value - a.value
// 变成倒序了
});
console.log(items);// [
{"name": "Magnetic","value": 100},
{"name": "And","value": 45},
{"name": "Sharpe","value": 37},
{"name": "Zeros","value": 37},
{"name": "Edward","value": 21},
{"name": "The","value": -12}
]
slice()
[slaɪs]
数组截取 ✨
slice()
,用于截取数组中的一部分,返回一个新的数组对象,不影响原数组。
注意 ❗ ❗ ❗ slice()
方法是浅拷贝,具体在下文做解释。
arr.slice(begin, end)
,slice
会提取原数组中索引从 begin
到 end
的所有元素(包含 begin
,但不包含 end
)。
begin 可选
是提取起始处的索引(从 0 开始),从该索引开始提取原数组元素。
-
如果该参数为负数,则表示从原数组中的倒数第几个元素开始提取,slice(-2) 表示提取原数组中的倒数第二个元素到最后一个元素(包含最后一个元素)。
-
如果省略
begin
,则 slice 从索引 0 开始。 -
如果
begin
超出原数组的索引范围,则会返回空数组。
end 可选
是提取终止处的索引(从 0 开始),在该索引处结束提取原数组元素。slice 会提取原数组中索引从 begin 到 end 的所有元素(包含 begin,但不包含 end)。
-
slice(1,4)
会提取原数组中从第二个元素开始一直到第四个元素的所有元素 (索引为 1, 2, 3的元素)。 -
如果该参数为负数, 则它表示在原数组中的倒数第几个元素结束抽取。
slice(-2,-1)
表示抽取了原数组中的倒数第二个元素到最后一个元素(不包含最后一个元素,也就是只有倒数第二个元素)。 -
如果
end
被省略,则slice
会一直提取到原数组末尾。 -
如果
end
大于数组的长度,slice
也会一直提取到原数组末尾。
❗ ❗ ❗ slice()
方法的浅拷贝
slice 不会修改原数组,只会返回一个浅复制了原数组中的元素的一个新数组。原数组的元素会按照下述规则拷贝:
- 如果该元素是个对象引用 (不是实际的对象),
slice
会拷贝这个对象引用到新的数组里。两个对象引用都引用了同一个对象。如果被引用的对象发生改变,则新的和原来的数组中的这个元素也会发生改变。 - 对于字符串、数字及布尔值来说(不是 String、Number 或者 Boolean 对象),
slice
会拷贝这些值到新的数组里。在别的数组里修改这些字符串或数字或是布尔值,将不会影响另一个数组。
如果向两个数组任一中添加了新元素,则另一个不会受到影响。
下面通过实例详细了解一下 slice()
方法的浅拷贝:
下面的代码描述了修改数组的几种情况:
let menuTreeList = [{
"id": "cfda8029dfb311e7b555201a068c6482",
"name": "系统管理",
"menuType": 0,
"children": [{
"id": "3873ccc2dfda11e7b555201a068c6483",
"name": "菜单管理",
"menuType": 2,
"children": [{
"id": "18bf8d5df09511e78a57201a068c6484",
"name": "新增",
"menuType": 1
},
{
"id": "18bf8d5df09511e78a57201a068c6485",
"name": "修改",
"menuType": 1
}
]
}]
},
{
"id": "cfda8029dfb311e7b555201a068c6486",
"name": "设备管理",
"menuType": 0,
"children": [{
"id": "18bf8d5df09511e78a57201a068c6487",
"name": "新增",
"menuType": 1
},
{
"id": "18bf8d5df09511e78a57201a068c6488",
"name": "修改",
"menuType": 1
}
]
}
]
let a = menuTreeList.slice(0, 1);
console.group("1.修改对象深层属性")
// console.log('a :>> ', a);
// 1.被引用的对象发生改变,则新的和原来的数组中的这个元素也会发生改变:
// 修改原始值 menuTreeList[0] ,即修改对象的引用
menuTreeList[0].children = [];
// 验证:
// 原来的数组:
console.log('被修改过的原来的数组 menuTreeList :>> ', menuTreeList);
// slice方法产生的新数组:
console.log('新的数组 a :>> ', a);
console.groupEnd()
let newArr = [1, 2, 3, 4, 5, 6];
let b = newArr.slice(0, 4);
console.group("2.验证数组元素为字符串、数字及布尔值时的情况")
// console.log('b :>> ', b);
// 2.对于字符串、数字及布尔值来说,slice 会拷贝这些值到新的数组里。
// 在别的数组里修改这些字符串或数字或是布尔值,将不会影响另一个数组:
newArr[0] = 0;
newArr[1] = 0;
newArr[2] = 0;
newArr[3] = 0;
// 原来的数组:
console.log('被修改过的原来的数组 newArr :>> ', newArr);
// slice方法产生的新数组:
console.log('新的数组 b :>> ', b);
console.groupEnd();
let newArr3 = [{
"id": "1",
"name": "设备管理",
"menuType": 0,
}, {
"id": "2",
"name": "设备管理",
"menuType": 0,
}, {
"id": "3",
"name": "设备管理",
"menuType": 0,
}, {
"id": "4",
"name": "设备管理",
"menuType": 0,
}];
let d = newArr3.slice(0, 3);
console.group("3.修改简单对象的属性 验证")
// console.log('d :>> ', d);
newArr3[0].id = "111111111";
newArr3[1].id = "111111111";
newArr3[2].id = "111111111";
// 原来的数组:
console.log('被修改过的原来的数组 newArr3 :>> ', newArr3);
// slice方法产生的新数组:
console.log('新的数组 d :>> ', d);
console.groupEnd();
let newArr2 = [{
"id": "1",
"name": "设备管理",
"menuType": 0,
}, {
"id": "2",
"name": "设备管理",
"menuType": 0,
}, {
"id": "3",
"name": "设备管理",
"menuType": 0,
}, {
"id": "4",
"name": "设备管理",
"menuType": 0,
}];
let c = newArr2.slice(0, 3);
console.group("4.把数组简单对象置空 验证")
// console.log('c :>> ', c);
newArr2[0] = {};
newArr2[1] = {};
newArr2[2] = {};
// 原来的数组:
console.log('被修改过的原来的数组 newArr2 :>> ', newArr2);
// slice方法产生的新数组:
console.log('新的数组 c :>> ', c);
console.groupEnd()
let newArr4 = [{
"id": "1",
"name": "设备管理",
"menuType": 0,
}, {
"id": "2",
"name": "设备管理",
"menuType": 0,
}, {
"id": "3",
"name": "设备管理",
"menuType": 0,
}, {
"id": "4",
"name": "设备管理",
"menuType": 0,
}];
let e = newArr4.slice(0, 3);
console.group("5.把数组简单对象元素改为基本数据类型 验证")
newArr4[0] = 0;
newArr4[1] = 0;
newArr4[2] = 0;
// 原来的数组:
console.log('被修改过的原来的数组 newArr4 :>> ', newArr4);
// slice方法产生的新数组:
console.log('新的数组 e :>> ', e);
console.groupEnd()
输出结果:
为什么把数组简单对象元素改为基本数据类型
和把数组简单对象置空
这两种情况下的数组都没有跟着改变呢?
这个问题我是向 CSDN博客专家「零一」学习的,字节跳动大佬,很多高质量原创文章,快来观摩👉✨「零一」✨👈
问题解析:
我们可以这样立即,[q, w, e]
,其实这个数组中第一个元素就是变量q,那么他指向的是一个对象,
- 如果修改该对象内部的属性,那么变量q仍然只是指向这个对象,对象的内存地址没变
- 如果直接把数组中第一个元素修改为空对象,那么就相当于
q = {}
,那指向的肯定跟原来的不一样了
即原来数组里的元素改为了新的对象,使用了新的对象引用,新数组里的元素对象依然存储在堆里,使用的是旧的对象引用。
我们接着看下面这个例子:
let newArr6 = [{
"id": "1",
"name": "设备管理",
"menuType": 0,
}, {
"id": "2",
"name": "设备管理",
"menuType": 0,
}, {
"id": "3",
"name": "设备管理",
"menuType": 0,
}, {
"id": "4",
"name": "设备管理",
"menuType": 0,
}];
let f = newArr6.slice(0, 3);
console.group("6.把数组简单对象设置为新的对象 验证")
// console.log('c :>> ', c);
newArr6[0] = {
"sss": "4444",
"aaaa": "对方是否",
};
newArr6[1] = {
"sss": "4444",
"aaaa": "对方是否",
};;
newArr6[2] = {
"sss": "4444",
"aaaa": "对方是否",
};;
// 原来的数组:
console.log('被修改过的原来的数组 newArr6 :>> ', newArr6);
// slice方法产生的新数组:
console.log('新的数组 f :>> ', f);
console.groupEnd()
输出结果:
其实不管是把对象改为基本数据类型,还是重新赋一个新的对象,他们都属于一类,都是修改了对象的指向
这里和基本的对象引用赋值做一个对比:
let menuTreeList = [{
"id": "cfda8029dfb311e7b555201a068c6482",
"name": "系统管理",
"menuType": 0,
"children": [{
"id": "3873ccc2dfda11e7b555201a068c6483",
"name": "菜单管理",
"menuType": 2,
"children": [{
"id": "18bf8d5df09511e78a57201a068c6484",
"name": "新增",
"menuType": 1
},
{
"id": "18bf8d5df09511e78a57201a068c6485",
"name": "修改",
"menuType": 1
}
]
}]
},
{
"id": "cfda8029dfb311e7b555201a068c6486",
"name": "设备管理",
"menuType": 0,
"children": [{
"id": "18bf8d5df09511e78a57201a068c6487",
"name": "新增",
"menuType": 1
},
{
"id": "18bf8d5df09511e78a57201a068c6488",
"name": "修改",
"menuType": 1
}
]
}
]
let a = menuTreeList;
console.group("1.修改对象深层属性")
menuTreeList[0].children = [];
// 验证:
// 原来的数组:
console.log('被修改过的原来的数组 menuTreeList :>> ', menuTreeList);
console.log('新的数组 a :>> ', a);
console.groupEnd()
let newArr = [1, 2, 3, 4, 5, 6];
let b = newArr;
console.group("2.验证数组元素为字符串、数字及布尔值时的情况")
newArr[0] = 0;
newArr[1] = 0;
newArr[2] = 0;
newArr[3] = 0;
// 原来的数组:
console.log('被修改过的原来的数组 newArr :>> ', newArr);
console.log('新的数组 b :>> ', b);
console.groupEnd();
let newArr3 = [{
"id": "1",
"name": "设备管理",
"menuType": 0,
}, {
"id": "2",
"name": "设备管理",
"menuType": 0,
}, {
"id": "3",
"name": "设备管理",
"menuType": 0,
}, {
"id": "4",
"name": "设备管理",
"menuType": 0,
}];
let d = newArr3;
console.group("3.修改简单对象的属性 验证")
newArr3[0].id = "111111111";
newArr3[1].id = "111111111";
newArr3[2].id = "111111111";
// 原来的数组:
console.log('被修改过的原来的数组 newArr3 :>> ', newArr3);
console.log('新的数组 d :>> ', d);
console.groupEnd();
let newArr2 = [{
"id": "1",
"name": "设备管理",
"menuType": 0,
}, {
"id": "2",
"name": "设备管理",
"menuType": 0,
}, {
"id": "3",
"name": "设备管理",
"menuType": 0,
}, {
"id": "4",
"name": "设备管理",
"menuType": 0,
}];
let c = newArr2;
console.group("4.把数组简单对象置空 验证")
newArr2[0] = {};
newArr2[1] = {};
newArr2[2] = {};
// 原来的数组:
console.log('被修改过的原来的数组 newArr2 :>> ', newArr2);
console.log('新的数组 c :>> ', c);
console.groupEnd()
let newArr4 = [{
"id": "1",
"name": "设备管理",
"menuType": 0,
}, {
"id": "2",
"name": "设备管理",
"menuType": 0,
}, {
"id": "3",
"name": "设备管理",
"menuType": 0,
}, {
"id": "4",
"name": "设备管理",
"menuType": 0,
}];
let e = newArr4;
console.group("5.把数组简单对象元素改为基本数据类型 验证")
newArr4[0] = 0;
newArr4[1] = 0;
newArr4[2] = 0;
// 原来的数组:
console.log('被修改过的原来的数组 newArr4 :>> ', newArr4);
console.log('新的数组 e :>> ', e);
console.groupEnd()
splice()
[splaɪs]
数组删除、替换或插入
splice()
方法通过删除或替换现有元素或者原地添加新的元素来修改数组,并以数组形式返回被修改的内容。此方法会改变原数组。
语法:
array.splice(start, deleteCount, item1, item2, ...)
start
指定修改的开始位置(从0计数)。如果超出了数组的长度,则从数组末尾开始添加内容;如果是负值,则表示从数组末位开始的第几位(从-1计数,这意味着-n是倒数第n个元素并且等价于array.length-n);如果负数的绝对值大于数组的长度,则表示开始位置为第0位。
deleteCount 可选
整数,表示要移除的数组元素的个数。
- 如果
deleteCount
大于start
之后的元素的总数,则从start
后面的元素都将被删除(含第start
位)。 - 如果
deleteCount
被省略了,或者它的值大于等于array.length - start
(也就是说,如果它大于或者等于start
之后的所有元素的数量),那么start
之后数组的所有元素都会被删除。 - 如果
deleteCount
是0
或者负数,则不移除元素。这种情况下,至少应添加一个新元素。
item1, item2, ... 可选
要添加进数组的元素,从start 位置开始。如果不指定,则 splice()
将只删除数组元素。
由被删除的元素组成的一个数组。如果只删除了一个元素,则返回只包含一个元素的数组。如果没有删除元素,则返回空数组。
如果添加进数组的元素个数不等于被删除的元素个数,数组的长度会发生相应的改变。
示例:
🔶 数组 插入元素,从索引 2 的位置开始删除 0 个元素,插入“drum”
var myFish = ["angel", "clown", "mandarin", "sturgeon"];
var removed = myFish.splice(2, 0, "drum");
// 运算后的 myFish: ["angel", "clown", "drum", "mandarin", "sturgeon"]
// 被删除的元素: [], 没有元素被删除
🔶 数组 删除元素,从索引 3 的位置开始删除 1 个元素
var myFish = ['angel', 'clown', 'drum', 'mandarin', 'sturgeon'];
var removed = myFish.splice(3, 1);
// 运算后的 myFish: ["angel", "clown", "drum", "sturgeon"]
// 被删除的元素: ["mandarin"]
🔶 数组 替换元素,索引 2 的位置开始删除 1 个元素,插入“trumpet”
var myFish = ['angel', 'clown', 'drum', 'sturgeon'];
var removed = myFish.splice(2, 1, "trumpet");
// 运算后的 myFish: ["angel", "clown", "trumpet", "sturgeon"]
// 被删除的元素: ["drum"]
🔶 数组 替换元素,从索引 0 的位置开始删除 2 个元素,插入"parrot"、"anemone"和"blue"
var myFish = ['angel', 'clown', 'trumpet', 'sturgeon'];
var removed = myFish.splice(0, 2, 'parrot', 'anemone', 'blue');
// 运算后的 myFish: ["parrot", "anemone", "blue", "trumpet", "sturgeon"]
// 被删除的元素: ["angel", "clown"]
🔶 数组 删除某索引后的所有元素,从索引 2 的位置开始删除所有元素
var myFish = ['angel', 'clown', 'mandarin', 'sturgeon'];
var removed = myFish.splice(2);
// 运算后的 myFish: ["angel", "clown"]
// 被删除的元素: ["mandarin", "sturgeon"]
数组查找指定元素
🍅 indexOf()
indexOf()
方法返回在数组中可以找到一个给定元素的第一个索引,如果不存在,则返回-1。
indexOf()
使用严格相等(strict equality,即 ===)
比较 searchElement
和数组中的元素。
语法:
arr.indexOf(searchElement, fromIndex)
searchElement
要查找的元素
fromIndex 可选
开始查找的位置。
🔶 找出指定元素出现的所有位置 (注意,是所有元素,一个元素在数组中可能出现多次)
var indices = [];
var array = ['a', 'b', 'a', 'c', 'a', 'd'];
var element = 'a';
var idx = array.indexOf(element);
while (idx != -1) {
indices.push(idx);
idx = array.indexOf(element, idx + 1);
}
console.log(indices);
// [0, 2, 4]
🔶 可以用于判断一个元素是否在数组里
🍅 lastIndexOf()
lastIndexOf()
方法返回指定元素在数组中的最后一个的索引,如果不存在则返回 -1。从数组的后面向前查找,从 fromIndex 处开始。
lastIndexOf
使用严格相等(strict equality,即 ===)
比较 searchElement
和数组中的元素。
🍅 includes()
includes()
方法用来判断一个数组是否包含一个指定的值,根据情况,如果包含则返回 true
,否则返回false
。
const array1 = [1, 2, 3];
console.log(array1.includes(2));// true
const pets = ['cat', 'dog', 'bat'];
console.log(pets.includes('cat'));// true
console.log(pets.includes('at'));// false
🍅 find()
find()
方法对数组中的每一项元素执行一次 callback 函数,直至有一个 callback
返回 true
。当找到了这样一个元素后,该方法会立即返回这个元素的值
,否则返回 undefined
。
const array1 = [5, 12, 8, 130, 44];
const found = array1.find(element => element > 10);// 12
🔶 用对象的属性查找数组里的对象
var inventory = [
{name: 'apples', quantity: 2},
{name: 'bananas', quantity: 0},
{name: 'cherries', quantity: 5}
];
function findCherries(fruit) {
return fruit.name === 'cherries';
}
console.log(inventory.find(findCherries)); // { name: 'cherries', quantity: 5 }
🍅 findIndex()
findIndex()
方法返回数组中满足提供的测试函数的第一个元素的索引。若没有找到对应元素则返回-1。
const array1 = [5, 12, 8, 130, 44];
const isLargeNumber = (element) => element > 13;
console.log(array1.findIndex(isLargeNumber));// 3
数组迭代
🍅 forEach()
forEach()
方法对数组的每个元素执行一次给定的函数。
const array1 = ['a', 'b', 'c'];
array1.forEach(element => console.log(element));
// expected output: "a"
// expected output: "b"
// expected output: "c"
🔶 将 for 循环转换为 forEach
const items = ['item1', 'item2', 'item3'];
const copy = [];
// before
for (let i=0; i<items.length; i++) {
copy.push(items[i]);
}
// after
items.forEach(function(item){
copy.push(item);
});
🔶 扁平化数组
下面的示例仅用于学习目的。如果你想使用内置方法来扁平化数组,你可以考虑使用 Array.prototype.flat()
(预计将成为 ES2019 的一部分,并且已在主要浏览器中实现)
/**
* Flattens passed array in one dimensional array
*
* @params {array} arr
* @returns {array}
*/
function flatten(arr) {
const result = [];
arr.forEach((i) => {
if (Array.isArray(i))
result.push(...flatten(i));
else
result.push(i);
})
return result;
}
// Usage
const problem = [1, 2, 3, [4, 5, [6, 7], 8, 9]];
flatten(problem); // [1, 2, 3, 4, 5, 6, 7, 8, 9]
🍅 map()
map()
方法创建一个新数组,该方法会给原数组中的每个元素都按顺序调用一次 callback
函数。返回一个由原数组每个元素执行回调函数的结果组成的新数组
。
const array1 = [1, 4, 9, 16];
// pass a function to map
const map1 = array1.map(x => x * 2);
console.log(map1);
// expected output: Array [2, 8, 18, 32]
🍅 filter()
filter()
方法创建一个新数组,该方法为数组中的每个元素调用一次 callback 函数,并且将所有使 callback
返回 true
或等价于 true 的值
的元素创建一个新数组
。
filter 不会改变原数组,它返回过滤后的新数组。
const words = ['spray', 'limit', 'elite', 'exuberant', 'destruction', 'present'];
const result = words.filter(word => word.length > 6);
console.log(result);
// expected output: Array ["exuberant", "destruction", "present"]
🔶 筛选排除所有较小的值
function isBigEnough(element) {
return element >= 10;
}
var filtered = [12, 5, 8, 130, 44].filter(isBigEnough);
// filtered is [12, 130, 44]
🍅 every()
every()
方法测试一个数组内的所有元素是否都能通过某个指定函数的测试。它返回一个布尔值。
注意:若收到一个空数组,此方法在一切情况下都会返回 true。
const isBelowThreshold = (currentValue) => currentValue < 40;
const array1 = [1, 30, 39, 29, 10, 13];
array1.every(isBelowThreshold) //true
every
方法为数组中的每个元素执行一次 callback
函数,直到它找到一个会使 callback
返回 falsy
的元素。如果发现了一个这样的元素,every
方法将会立即返回 false
。否则,callback
为每一个元素返回 true
,every
就会返回 true
。
🔶 检测所有数组元素的大小
下例检测数组中的所有元素是否都大于 10。
function isBigEnough(element, index, array) {
return element >= 10;
}
[12, 5, 8, 130, 44].every(isBigEnough); // false
[12, 54, 18, 130, 44].every(isBigEnough); // true
🔶 使用箭头函数
箭头函数为上面的检测过程提供了更简短的语法。
[12, 5, 8, 130, 44].every(x => x >= 10); // false
[12, 54, 18, 130, 44].every(x => x >= 10); // true
🍅 some()
some() 方法测试数组中是不是至少有1个元素通过了被提供的函数测试。它返回的是一个Boolean类型的值。
注意:如果用一个空数组进行测试,在任何情况下它返回的都是
false
。
some()
为数组中的每一个元素执行一次 callback
函数,直到找到一个使得 callback
返回一个“真值”(即可转换为布尔值 true
的值)。如果找到了这样一个值,some()
将会立即返回 true
。否则,some()
返回 false
。
🔶 测试数组元素的值
下面的例子检测在数组中是否有元素大于 10。
function isBiggerThan10(element, index, array) {
return element > 10;
}
[2, 5, 8, 1, 4].some(isBiggerThan10); // false
[12, 5, 8, 1, 4].some(isBiggerThan10); // true
🔶 使用箭头函数测试数组元素的值
箭头函数 可以通过更简洁的语法实现相同的用例.
[2, 5, 8, 1, 4].some(x => x > 10); // false
[12, 5, 8, 1, 4].some(x => x > 10); // true
reduce()
数组归并
参考这篇文章:取数组的最大值(ES5、ES6),详解Math.max() 和 reduce() API
flat()
数组扁平化
flat() 方法会按照一个可指定的深度递归遍历数组,并将所有元素与遍历到的子数组中的元素合并为一个新数组返回。
语法
var newArray = arr.flat(depth)
depth 可选
指定要提取嵌套数组的结构深度,默认值为 1。
返回一个包含将数组与子数组中所有元素的新数组。
🔶 扁平化嵌套数组
var arr1 = [1, 2, [3, 4]];
arr1.flat();
// [1, 2, 3, 4]
var arr2 = [1, 2, [3, 4, [5, 6]]];
arr2.flat();
// [1, 2, 3, 4, [5, 6]]
var arr3 = [1, 2, [3, 4, [5, 6]]];
arr3.flat(2);
// [1, 2, 3, 4, 5, 6]
🔶 扁平化与移除数组空项
flat() 方法会移除数组中的空项:
var arr4 = [1, 2, , 4, 5];
arr4.flat();
// [1, 2, 4, 5]