本文为【JavaScript 漫游】专栏的第 011 篇文章,记录的内容包含了 ES5 规范中Array
对象的所有方法。
Array()
Array.isArray()
valueOf()
、toString()
push()
、pop()
shift()
、unshift()
join()
concat()
reverse()
slice()
splice()
sort()
map()
forEach()
filter()
some()
、every()
reduce()
、reduceRight()
indexOf()
、lastIndexOf()
Array()
构造函数
Array
是 JS 的原生对象,同时也是一个构造函数,可以用它生成新的数组。
var arr = new Array(2);
arr.length // 2
arr // [ empty x 2 ]
Array
构造函数是有缺陷的,直接使用数组字面量是更好的做法。
// bad
var arr = new Array(1, 2);
// good
var arr = [1, 2];
Array.isArray()
静态方法
返回一个布尔值,表示参数是否为数组。它可以弥补 typeof
运算符的不足。
var arr = [1, 2, 3];
typeof arr // "object"
Array.isArray(arr) // true
**valueOf()
和 toString()
**
valueOf
方法是一个所有对象都拥有的方法,表示对该对象求值。不同对象的 valueOf
方法不尽一致,数组的 valueOf
方法返回数组本身。
var arr = [1, 2, 3];
arr.valueOf() // [1, 2, 3]
toString
方法也是对象的通用方法,数组的 toString
方法返回数组的字符串形式。
var arr = [1, 2, 3];
arr.toString() // "1,2,3"
var arr = [1, 2, 3, [4, 5, 6]];
arr.toString() // "1,2,3,4,5,6"
push()
和 pop()
push
方法用于在数组的末端添加一个或多个元素,并返回添加新元素后的数组长度。注意,它会改变原数组。
var arr = [];
arr.push(1) // 1
arr.push('a') // 2
arr.push(true, {}) // 4
arr // [1, 'a', true, {}]
pop
方法用于删除数组的最后一个元素,并返回该元素。注意,它同样会改变原数组。
var arr = ['a', 'b', 'c'];
arr.pop() // 'c'
arr // ['a', 'b']
shift()
和 unshift()
shift
方法用于删除数组的第一个元素,并返回该元素。注意,该方法会改变原数组。
var a = ['a', 'b', 'c'];
a.shift() // 'a'
a // ['b', 'c']
unshift
方法用于在数组的第一个位置添加元素,并返回添加新元素后的数组长度。注意,该方法会改变原数组。
var a = ['a', 'b', 'c'];
a.unshift('x'); // 4
a // ['x', 'a', 'b', 'c']
unshift
方法可以接受多个参数,这些参数都会添加到目标数组头部。
var arr = [ 'c', 'd' ];
arr.unshift('a', 'b') // 4
arr // [ 'a', 'b', 'c', 'd' ]
join()
join
方法以指定参数作为分隔符,将所有数组成员连接为一个字符串返回。如果不提供参数,默认用逗号分隔。
var a = [1, 2, 3, 4];
a.join(' ') // '1 2 3 4'
a.join(' | ') // "1 | 2 | 3 | 4"
a.join() // "1,2,3,4"
concat()
concat
方法用于多个数组的合并。它将新数组的成员,添加到原数组成员的后部,然后返回一个新数组,原数组不变。
['hello'].concat(['world'])
// ["hello", "world"]
['hello'].concat(['world'], ['!'])
// ["hello", "world", "!"]
[].concat({a: 1}, {b: 2})
// [{ a: 1 }, { b: 2 }]
[2].concat({a: 1})
// [2, {a: 1}]
reverse()
reverse
方法用于颠倒排列数组元素,返回改变后的数组。注意,该方法将改变原数组。
var a = ['a', 'b', 'c'];
a.reverse() // ["c", "b", "a"]
a // ["c", "b", "a"]
slice()
slice
方法用于提取目标数组的一部分,返回一个新数组,原数组不变。
arr.slice(start, end);
如果 slice
方法的参数是负数,则表示倒数计算的位置。
var a = ['a', 'b', 'c'];
a.slice(-2) // ["b", "c"]
a.slice(-2, -1) // ["b"]
splice()
splice
方法用于删除原数组的一部分成,并可以在删除的位置添加新的数组成员,返回值是被删除的元素。注意,该方法会改变原数组。
arr.splice(start, count, addElement1, addElement2, ...);
起始位置如果是负数,就表示从倒数位置开始删除。
var a = ['a', 'b', 'c', 'd', 'e', 'f'];
a.splice(-4, 2) // ["c", "d"]
如果只是单纯地插入元素,splice
方法的第二个参数可以设为 0
var a = [1, 1, 1];
a.splice(1, 0, 2) // []
a // [1, 2, 1, 1]
sort()
sort
方法对数组成员进行排序,默认是按照字典顺序排序。排序后,原数组将被改变。
['d', 'c', 'b', 'a'].sort()
// ['a', 'b', 'c', 'd']
[4, 3, 2, 1].sort()
// [1, 2, 3, 4]
[11, 101].sort()
// [101, 11]
[10111, 1101, 111].sort()
// [10111, 1101, 111]
需要注意的是,sort
方法不是按照大小排序,而是按照字典排序。也就是说,数值会被先转成字符串,再按照字典顺序进行比较,所以 101
排在 11
的前面。
map()
map
方法将数组的所有成员依次传入参数函数,然后把每一次的执行结果组成一个新数组返回。
var numbers = [1, 2, 3];
numbers.map(function (n) {
return n + 1;
});
// [2, 3, 4]
numbers
// [1, 2, 3]
map
方法在日常开发中使用频率极高。
forEach()
forEach
方法与 map
方法很相似,也是对数组的所有成员依次执行参数函数。但是,forEach
方法不返回值,只用来操作数据。这就是说,如果数组遍历的目的是为了得到返回值,那么使用 map
方法,否则使用 forEach
方法。
forEach
的用法与 map
方法一致,参数是一个函数,该函数同样接受三个参数:当前值、当前位置、整个数组。
function log(element, index, array) {
console.log('[' + index + '] = ' + element);
}
[2, 5, 9].forEach(log);
// [0] = 2
// [1] = 5
// [2] = 9
值得注意的是,forEach
方法无法中断执行,总是会将所有成员遍历完。如果希望符合某种条件时,就中断遍历,要使用 for
循环。
var arr = [1, 2, 3];
for (var i = 0; i < arr.length; i++) {
if (arr[i] === 2) break;
console.log(arr[i]);
}
// 1
filter()
filter
方法用于过滤数组成员,满足条件的成员组成一个新数组返回。
它的参数是一个函数,所有数组成员依次执行该函数,返回结果为true的成员组成一个新数组返回。该方法不会改变原数组。
[1, 2, 3, 4, 5].filter(function (elem) {
return (elem > 3);
})
// [4, 5]
filter
方法的参数函数可以接受三个参数:当前成员,当前位置和整个数组。
[1, 2, 3, 4, 5].filter(function (elem, index, arr) {
return index % 2 === 0;
});
// [1, 3, 5]
some()
和 every()
这两个方法都返回一个布尔值,表示判断数组成员是否符合某种条件。
它们接受一个函数作为参数,所有数组成员依次执行该函数。该函数接受三个参数:当前成员、当前位置和整个数组,然后返回一个布尔值。
some
方法是只要一个成员的返回值是 true
,则整个 some
方法的返回值就是 true
,否则返回 false
。
var arr = [1, 2, 3, 4, 5];
arr.some(function (elem, index, arr) {
return elem >= 3;
});
// true
every
方法是所有成员的返回值都是 true
,整个 every
方法才返回 true
,否则返回 false
。
var arr = [1, 2, 3, 4, 5];
arr.every(function (elem, index, arr) {
return elem >= 3;
});
// false
reduce()
和 reduceRight()
reduce
方法和 reduceRight
方法依次处理数组的每个成员,最终累计为一个值。它们的差别是,reduce
是从左到右处理,reduceRight
则是从右到左,其他完全一样。
[1, 2, 3, 4, 5].reduce(function (a, b) {
console.log(a, b);
return a + b;
})
// 1 2
// 3 3
// 6 4
// 10 5
//最后结果:15
reduce
方法和 reduceRight
方法的第一个参数都是一个函数。该函数接受以下四个参数。
这四个参数之中,只有前两个是必须的,后两个则是可选的。
如果要对累积变量指定初值,可以把它放在 reduce
方法和 reduceRight
方法的第二个参数。
[1, 2, 3, 4, 5].reduce(function (a, b) {
return a + b;
}, 10);
// 25
indexOf()
和 lastIndexOf()
indexOf
方法返回给定元素在数组中第一次出现的位置,如果没有出现则返回 -1
。
var a = ['a', 'b', 'c'];
a.indexOf('b') // 1
a.indexOf('y') // -1
indexOf
方法还可以接受第二个参数,表示搜索的开始位置。
['a', 'b', 'c'].indexOf('a', 1) // -1
lastIndexOf
方法返回给定元素在数组中最后一次出现的位置,如果没有出现则返回 -1
。
var a = [2, 5, 9, 2];
a.lastIndexOf(2) // 3
a.lastIndexOf(7) // -1
注意,这两个方法不能用来搜索 NaN
的位置,即它们无法确定数组成员是否包含 NaN
。
[NaN].indexOf(NaN) // -1
[NaN].lastIndexOf(NaN) // -1
这是因为这两个方法内部,使用严格相等运算符(===
)进行比较,而 NaN
是唯一一个不等于自身的值。