1、构造函数
Array是 JavaScript 的原生对象,同时也是一个构造函数,可以用它生成新的数组。
let arr = new Array(2);
arr.length //2
arr // [empty*2]
上面代码中,Array()构造函数的参数2,表示生成一个两个成员的数组,每个位置都是空值。
如果没有使用new关键字,运行结果也是一样的。考虑到语义性最好总是加上new
let arr = new Array(2);
//等同于
let arr = Array(2);
Array()构造函数有一个很大的缺陷,不同的参数个数会导致不一致的行为。
//无参数时返回空数组
new Array(); // []
//单个正整数参数 返回数组长度
new Array(2); //[empty*2]
//非正整数数值作为参数会报错 会报错
new Array(1.2);
new Array(-2);
// RangeError: Invalid array length
//单个非数值作为参数 例如布尔值、对象、字符串等 则该参数返回的是新数组的成员
new Array('qwer') // ['qwer']
new Array([1]) // [Array[1]]
//多参数时返回新数组成员
new Array(1,2) // [1,2]
new Array('q','w','e','r') // ['q','w','e','r']
所以建议写法为
//bad
let arr = new Array(1,2);
//good
let arr = [1,2]
注意一种特殊情况
let a = new Array(3);
let b = [undefined,undefined,undefined]
a.length //3
b.length //3
a[0] // undefined
b[0] // undefined
0 in a // false
0 in b // true
a的键名(成员的序号)都是空的,b的键名是有值的。
2、静态方法
2.1 Array.isArray()
Array.isArray方法返回一个布尔值,表示参数是否为数组。它可以弥补typeof运算符的不足
let arr = [1, 2, 3];
typeof arr // "object"
Array.isArray(arr) // true
3、实例方法
3.1 valueOf(), toString()
valueOf方法是一个所有对象都拥有的方法,表示对该对象求值。不同对象的valueOf方法不尽一致,数组的valueOf方法返回数组本身。
let arr = [1, 2, 3];
arr.valueOf() // [1, 2, 3]
toString方法也是对象的通用方法,数组的toString方法返回数组的字符串形式。
let arr1 = [1, 2, 3];
arr.toString() // "1,2,3"
let arr2 = [1, 2, 3, [4, 5, 6]];
arr.toString() // "1,2,3,4,5,6"
3.2 push(),pop()
push方法会在数组末尾添加一个元素或多个元素,并返回新数组的长度
push方法会改变原数组
let arr = [1,2,3]
let a = arr.push(5)
a // 4
arr // [1,2,3,5]
pop方法会在数组末尾删除一个元素
pop方法会改变原数组
let arr = [1,2]
let a1 = arr.pop()
a1 // 2
arr // [1]
arr.pop().pop() //undefined
对空数组使用pop方法,不会报错,而是返回undefined。
3.3 shift(),unshift()
shift方法删除数组的第一个元素 并返回该元素
shift方法会改变原数组
let arr = [1,2,3]
let a1 = arr.shift()
a1 // 1
arr // [2,3]
unshift方法在数组都一个位置添加一个新元素 并返回新数组的长度
unshift方法会改变原数组
let b1 = arr.unshift(0)
b1 // 3
arr // [0,2,3]
3.4 sort()
sort方法对数组成员进行排序,默认是按照字典顺序排序。排序后,原数组将被改变。
let arr = [11,2,3,4,5]
arr.sort() // [11,2,3,4,5]
sort()方法不是按照大小排序,而是按照字典顺序。也就是说,数值会被先转成字符串,再按照字典顺序进行比较,所以11排在2的前面。
如果想让sort方法按照自定义方式排序,可以传入一个函数作为参数。
[11, 2, 3].sort(function (a, b) {
return a - b;
})
[11, 2, 3].sort((a,b)=>a-b)
// [2, 3, 11]
3.5 splice()
splice()方法用于删除原数组的一部分成员,并可以在删除的位置添加新的数组成员,返回值是被删除的元素。
该方法会改变原数组
//开始下标 删除个数 新元素
arr.splice(start, count, addElement1, addElement2, ...);
let arr = ['a','b','c','d']
//从下标2开始删除两个 包含下标2
let a1 = arr.splice(2,2,1,2)
a1 // ['c','d']
arr // ['a','b',1,2]
如果只是插入元素,splice方法的第二个参数可以设为0。
let a = [1, 1, 1];
a.splice(1, 0, 2) // []
//在下标1前添加
a // [1, 2, 1, 1]
如果只提供第一个参数,等同于将原数组在指定位置拆分成两个数组。
let a = [1, 2, 3, 4];
a.splice(2) // [3, 4]
a // [1, 2]
3.6 reverse()
reverse方法用于颠倒排列数组元素,返回改变后的数组。注意,该方法将改变原数组。
let a = ['a', 'b', 'c'];
a.reverse() // ["c", "b", "a"]
a // ["c", "b", "a"]
3.2 ~3.6 以上7种方法会改变原数组
3.7 join()
join()方法以指定参数作为分隔符,将所有数组成员连接为一个字符串返回。如果不提供参数,默认用逗号分隔。
let a = [1,2,3,4]
a.join(' ') // '1 2 3 4'
a.join(' | ') // "1 | 2 | 3 | 4"
a.join() // "1,2,3,4"
如果数组成员是undefined或null或空位,会被转成空字符串。
3.8 concat()
concat方法用于多个数组的合并。它将新数组的成员,添加到原数组成员的后部,然后返回一个新数组,原数组不变。
let arr =[1,2]
let a1 = arr.concat([3,4])
a1 // [1,2,3,4]
arr // [1,2]
如果数组成员包括对象,concat方法返回当前数组的一个浅拷贝。所谓“浅拷贝”,指的是新数组拷贝的是对象的引用。
let obj = { a: 1 };
let oldArray = [obj];
let newArray = oldArray.concat();
obj.a = 2;
newArray[0].a // 2
上面代码中,原数组包含一个对象,concat方法生成的新数组包含这个对象的引用。所以,改变原对象以后,新数组跟着改变。
3.9 slice()
slice()方法用于提取目标数组的一部分,返回一个新数组,原数组不变。
arr.slice(start, end);
//从下标start开始 到end结束 不包含结束下标
如果省略第二个参数,则一直返回到原数组的最后一个成员。 如果没有参数,实际上等于返回一个原数组的拷贝。 如果参数为负数,则表示倒数计算的位置。
let a = ['a', 'b', 'c'];
a.slice(0) // ["a", "b", "c"]
a.slice(1) // ["b", "c"]
a.slice(1, 2) // ["b"]
a.slice(2, 6) // ["c"]
a.slice() // ["a", "b", "c"]
a.slice(-2) // ["b", "c"]
a.slice(-2, -1) // ["b"]
如果第一个参数大于等于数组长度,或者第二个参数小于第一个参数,则返回空数组。
let a = ['a', 'b', 'c'];
a.slice(4) // []
a.slice(2, 1) // []
slice()方法的一个重要应用,是将类似数组的对象转为真正的数组。
Array.prototype.slice.call({ 0: 'a', 1: 'b', length: 2 })
// ['a', 'b']
Array.prototype.slice.call(document.querySelectorAll("div"));
Array.prototype.slice.call(arguments);
上面代码的参数都不是数组,但是通过call方法,在它们上面调用slice()方法,就可以把它们转为真正的数组。
3.10 map()
map()方法将数组的所有成员依次传入参数函数,然后把每一次的执行结果组成一个新数组返回。
map()方法向它传入三个参数:当前成员、当前位置和数组本身。
数组.map(function(ele, index, arr) {
return ele * index;
});
//例 把数组每个成员+1
let arr1 = [2,5,7]
let arr2 = arr1.map(item=> item+1)
console.log(arr2) // [3,6,8]
如果数组有空位,map()方法的回调函数在这个位置不会执行,会跳过数组的空位。
let f = function (n) { return 'a' };
[1, undefined, 2].map(f) // ["a", "a", "a"]
[1, null, 2].map(f) // ["a", "a", "a"]
[1, , 2].map(f) // ["a", , "a"]
上面代码中,map()方法不会跳过undefined和null,但是会跳过空位
3.11 filter()
filter()方法用于过滤数组成员,满足条件的成员组成一个新数组返回。
它的参数是一个函数,所有数组成员依次执行该函数,返回结果为true的成员组成一个新数组返回。该方法不会改变原数组。
filter()方法的参数函数可以接受三个参数:当前成员,当前位置和整个数组
数组.filter(function (ele, index, arr) {
return index % 2 === 0;
});
// [1, 3, 5]
let arr = [0,"a",1,false]
let a1 = arr.filter(Boolean)
console.log(a1) //["a",1]
3.12 forEach()
forEach()方法与map()方法很相似,也是对数组的所有成员依次执行参数函数。但是,forEach()方法不返回值,只用来操作数据。这就是说,如果数组遍历的目的是为了得到返回值,那么使用map()方法,否则使用forEach()方法。
forEach()的用法与map()方法一致,参数是一个函数,该函数同样接受三个参数:当前值、当前位置、整个数组。
数组.forEach(function(ele, index, arr){
})
[1, , 2].forEach(log)
// 2
// 3
注意,`forEach()`方法无法中断执行,总是会将所有成员遍历完。如果希望符合某种条件时,就中断遍历,要使用`for`循环。
forEach()方法也会跳过数组的空位,不会跳过undefined和null
3.13 some() , every()
这两个方法类似“断言”(assert),返回一个布尔值,表示判断数组成员是否符合某种条件。
它们接受一个函数作为参数,所有数组成员依次执行该函数。该函数接受三个参数:当前成员、当前位置和整个数组,然后返回一个布尔值。
some方法是只要一个成员的返回值是true,则整个some方法的返回值就是true,否则返回false。
every方法是所有成员的返回值都是true,整个every方法才返回true,否则返回false。
let arr = [1, 2, 3, 4, 5];
arr.some(function (ele, index, arr) {
return ele >= 3;
});
// true
arr.every(function (ele, index, arr) {
return elem >= 3;
});
// false
3.14 reduce() ,reduceRight()
reduce()方法和reduceRight()方法依次处理数组的每个成员,最终累计为一个值。
它们的差别是,reduce()是从左到右处理(从第一个成员到最后一个成员),reduceRight()则是从右到左(从最后一个成员到第一个成员),其他完全一样。
如果要对累积变量指定初值,可以把它放在reduce()方法和reduceRight()方法的第二个参数。
[1, 2, 3, 4, 5].reduce(function (a, b) {
return a + b;
}, 10);
// 25
3.15 indexOf() , lastIndexOf()
indexOf方法返回给定元素在数组中第一次出现的位置,如果没有出现则返回-1
indexOf方法还可以接受第二个参数,表示搜索的开始位置。
let a = ['a', 'b', 'c'];
a.indexOf('b') // 1
a.indexOf('y') // -1
['a', 'b', 'c'].indexOf('a', 1) // -1
lastIndexOf()同理从后往前
3.17 flat()
var newArray = arr.flat([depth])
// depth 可选:指定要提取嵌套数组的结构深度,默认值为 1。
flat() 方法会按照一个可指定的深度递归遍历数组,并将所有元素与遍历到的子数组中的元素合并为一个新数组返回。
const list = [1, 2, [3, 4, [5, 6]]];
list.flat(Infinity); // [1, 2, 3, 4, 5, 6]
flatMap()
flatMap() 方法首先使用映射函数映射每个元素,然后将结果压缩成一个新数组。它与 map 连着深度值为1的 flat 几乎相同,但 flatMap 通常在合并成一种方法的效率稍微高一些
const list = [1, 2, 3];
list.flatMap((el) => [el, el * el]); // [1, 1, 2, 4, 3, 9]
3.18 at()
at() 方法接收一个整数值并返回该索引的项目,允许正数和负数。负整数从数组中的最后一个项目开始倒数。
// Code
const list = [1, 2, 3, 4, 5];
list.at(1); // 2
list.at(-1); // 5
list.at(-2); // 4
3.19 includes()
includes() 方法用来判断一个数组是否包含一个指定的值,根据情况,如果包含则返回 true,否则返回 false。
const list = [1, 2, 3, 4, 5];
list.includes(3); // true
list.includes(6); // false
3.20 find() ,findIndex()
find() 方法返回数组中满足提供的测试函数的第一个元素的值。否则返回 undefined
findIndex() 方法返回数组中满足提供的测试函数的第一个元素的索引。若没有找到对应元素则返回-1。
const list = [1, 2, 3, 4, 5];
list.find((el) => el === 3); // 3
list.find((el) => el === 6); // undefined
const array = [5, 12, 8, 130, 44];
array.findIndex((element) => element > 13); // 3
3.21 copyWithIn() ,fill() ....MDN
3.22 链式调用
let users = [
{name: 'tom', email: 'tom@example.com'},
{name: 'peter', email: 'peter@example.com'}
];
users.map(function (user) {
return user.email;
}).filter(function (email) {
//过滤以t开头的
return /^t/.test(email);
}).forEach(function (email) {
console.log(email);
});
// "tom@example.com"