原稿:语雀 · Array · 原目录:JavaScript › Array
关于Array API详情,见MDN
遍历
- 普通for循环:略
- 使用for-of遍历可迭代对象元素
let arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
for (let item of arr) {
console.log(item);
}
- 使用for-in遍历对象属性——数组索引
let arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
for (let item in arr) {
console.log(arr[item]);
}
- 使用forEach()
let arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
arr.forEach((value, index, array) => {
console.log(value);
});
拼接:concat()
在现有数组全部元素基础上创建一个新数组
返回新数组
创建一个当前数组的副本,然后再把它的参数添加到副本末尾,最后返回这个新构建的数组:如果传入一或多个数组,则concat()会把这些数组的每一项都添加到结果数组。如果参数非数组,则直接把它们添加到副本末尾
let colors = ["red", "green", "blue"];
let colors2 = colors.concat("yellow", ["black", "brown"]);
console.log(colors); // ["red", "green","blue"]
console.log(colors2); // ["red", "green", "blue", "yellow", "black", "brown"]
使用apply可实现原地拼接,而非返回新数组
let colors = ["red", "green", "blue"];
let colors2 = ["yellow", "black", "brown"];
Array.prototype.push.apply(colors, colors2);
console.log(colors);// (6) ['red', 'green', 'blue', 'yellow', 'black', 'brown']
切片:slice()
创建一个包含原数组中一或多个元素的新数组
返回新数组
接收最多2个参数,对应返回元素的开始索引和结束索引。如果只有一个参数,则slice()返回该索引到数组末尾的所有元素。如果有两个参数,则返回从开始索引到结束索引(不含结束处)对应的所有元素。
let colors = ["red", "green", "blue", "yellow", "purple"];
let colors2 = colors.slice(1);
let colors3 = colors.slice(1, 4);
alert(colors2); // green,blue,yellow,purple
alert(colors3); // green,blue,yellow
剪接:splice()
根据传参不同有3种不同的用途:插入/删除/替换,方法返回被删除项组成的数组(无删除项则返回空数组),所有操作发生在原始数组上
返回删除元素数组
let colors = ["red", "green", "blue"];
let removed = colors.splice(0,1); // 删除第一项
alert(colors); // green,blue
alert(removed); // red,只有一个元素的数组
removed = colors.splice(1, 0, "yellow", "orange"); // 在位置1 插入两个元素
alert(colors); // green,yellow,orange,blue
alert(removed); // 空数组
removed = colors.splice(1, 1, "red", "purple"); // 插入两个值,删除一个元素
alert(colors); // green,red,purple,orange,blue
alert(removed); // yellow,只有一个元素的数组
- 删除:传2个参数:要删除的第一个元素的位置和要删除的元素数量。可以从数组中删除任意多个元素,比如splice(0, 2)会删除前两个元素。
- 插入:传3个参数:开始位置、0(要删除的元素数量)和要插入的元素,可以在数组中指定的位置插入元素。第三个参数之后还可以传第四个、第五个参数,乃至任意多个要插入的元素。splice(2, 0, “red”, “green”)会从数组位置2开始插入字符串"red"和"green"
- 替换:实际上就是插入,当删除同时插入元素即可实现替换
拷贝
浅拷贝
使用ES6的Array.from()或展开操作
let arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
// 1. 展开
let arr1 = [...arr];
// 2. from()
let arr2 = Array.from(arr);
// 3. slice()
let arr = arr.slice();
深拷贝
语雀引用内容
迭代
迭代方法通过定义不同操作方便了对数组元素的处理,每个方法接收两个参数:迭代函数以及可选的作为函数运行上下文的作用域对象(影响函数中this值)
迭代函数接收3个参数:元素value、索引index和数组array,根据返回值可分组
返回boolean:every()/some()
every():对每个item都运行传入的函数,如果每一项返回true,则every()返回true
some():对每个item都运行传入的函数,如果有一项返回true,则some()返回true
let numbers = [1, 2, 3, 4, 5, 4, 3, 2, 1];
console.log(numbers.every((item, index, array) => item > 2)); // false
console.log(numbers.some((item, index, array) => item > 2)); // true
返回数组:map()/filter()
map():对每个item都运行传入的函数,返回由每次调用结果构成的数组
fillter():对每个item都运行传入的函数,返回true的项组成数组之后返回
map 和 filter 都返回新数组,原数组保持不变
实践:实现数组求交集、并集
let a = [1, 2, 3, 4];
let b = [1, 2, 3, 5];
function intersection(arr1, arr2) {
return arr1.filter((value) => arr2.indexOf(value) != -1);
}
function union(arr1, arr2) {
return arr1.concat(arr2.filter((value) => arr1.indexOf(value) == -1));
}
console.log(intersection(a, b));
console.log(union(a, b));
无返回值:forEach()
forEach():对每个item都运行传入的函数,没有返回值,见遍历数组操作
归并
reduce()/reduceRight()会迭代数组的所有项,根据归并函数计算一个最终返回值。reduce()正序,reduceRight()逆序。方法接收两个参数:归并函数和(可选)归并起点的初始值
归并函数接收4个参数:上一个归并值pre、当前项cur、当前项索引index、和数组array。当次计算值会作为下一次的pre,如果没有指定归并起点值,则首次迭代pre取array
,cur取array
下例使用reduce()累加数组中所有数值:
let values = [1, 2, 3, 4, 5];
let sum = values.reduce((prev, cur, index, array) => prev + cur);
alert(sum); // 15
- 第一次归并从values开始,prev=1,cur=2,返回3
- 第二次归并:prev=3,cur=3,返回6
- 第三次归并:prev=6,cur=4,返回10
- 第四次归并:prev=10,cur=5,返回15,结束归并
扁平化
语雀引用内容
判断 Array
首先强调不能通过 instanceof 判断,因为 2. 可以直接调用 Array.isArray(),或者自行实现(参考实用函数)
if (!Array.isArray) {
Array.isArray = function(arg) {
return Object.prototype.toString.call(arg) === '[object Array]';
};
}
- 判断 constructor(实际上为实例原型链上属性)
var arr = []
console.log(arr.constructor === Array)
- instanceof,但是该方法不可跨窗口访问
alert(parent.arr instanceof Array); //false
alert(parent.arr instanceof parent.window.Array); //true 这样才是true
数组去重
语雀引用内容
Map
Map 是一个带键的数据项的集合,就像一个 Object 一样。 但是它们最大的差别是 Map 允许任何类型的键(key)。它的方法和属性如下:
- new Map() —— 创建 map
- map.set(key, value) —— 根据键存储值
- map.get(key) —— 根据键来返回值,如果 map 中不存在对应的 key,则返回 undefined
- map.has(key) —— 如果 key 存在则返回 true,否则返回 false
- map.delete(key) —— 删除指定键的值。
- map.clear() —— 清空 map
- map.size —— 返回当前元素个数
- map.keys() —— 遍历并返回所有的键(returns an iterable for keys)
- map.values() —— 遍历并返回所有的值(returns an iterable for values)
- map.entries() —— 遍历并返回所有的实体(returns an iterable for entries)
与Object差异 2. Object只能使用数值、字符串或符号作为键,且会被转换为字符串,Map可使用任何数据类型作为key ,且保持该类型 4. Map实例会维护键值对的插入顺序,因此可以根据插入顺序执行迭代操作
WeakMap
Weak主要形容弱映射中的key是弱的——GC随时会回收弱映射的key,但是只要key存在,value就不会被回收
Set
Set 是一个特殊的类型集合 —— “值的集合”(没有键),它的每一个值只能出现一次。其方法和属性类似Map
WeakSet
WeakSet中的Weak形容集合中的value是弱的——这些值不属于正式的引用,不会阻止GC程序