数组
次访问
数组字面量
数组字面量提供了一种非常方便的创建数组的方法。一个数组表达式是在一对方括号内包围零个或多个用逗号分隔的值的表达式。
数组的第一个值的属性名是 0
。
1 | var empty = []; |
在大多数语言中,一个数组的所有元素都要求是相同的类型。js
允许数组包含任意混合类型的值:
1 | var misc = ['string', 98.6, true, false, null]; |
长度
每个数组都有一个 length
属性。和大多数的语言不同,js
中数组的 length
是没有上限的。如果用大于或等于 length
的数字作为下标来存储一个元素,那么 length
的值会被增大以便容纳新的值,不会发生数组越界的错误。可以直接设置 length
的值,如果 length
大于当前的 length
值,则更大的那些下标的值都是 undefined
;如果更小,
那么将会把所有下标大于等于新 length
的属性给删除。通过把下标指定为一个数组的当前 length
,可以附加一个新元素到该数组的末尾。
1 | var arr = ['one', 'two', 'three']; |
删除
由于 js
的数组其实就是对象,所以 delete
运算符可以删除数组的元素:
1 | var arr = ['one', 'two', 'three']; |
遗憾的是删除后的数组直接留了一个空位值是 undefined
,幸运的是可以通过数组的 splice
方法来进行调整。splice
方法接受 2
个参数,第一个是数组的序号,第二个是删除的元素个数,并且返回一个数组,这个数组包含了所有的删除元素。
1 | arr.splice(1, 1); // [undefined] |
枚举
因为 js
数组其实就是对象,所以 for in
语句可以用来遍历一个数组的所有属性。但是用 for in
语句无法保证顺序。所以遍历还是用常规的 for
循环
1 | var numbers = [1, 2, 3, 4, 5]; |
判断是否是数组
1 | typeof [1, 2, 3]; // 'object' |
js
本身对于数组和对象的区别是混乱的。typeof
运算符报告数组的类型是 object
,没有任何意义。js
没有一个好的机制来区别是数组还是对象,但是我们可以自己实现一个 is_array
函数来弥补这个缺陷:
1 | var isArray = function( obj ) { |
上面这个判断基本在常规页面就能很好的区分出数组还是对象了。但是也有特例,比如在不同的窗口(window
)或帧(frame
)就会失败。这个时候可以用下面这个替换:
1 | var isArray = function( obj ) { |
判断某个对象是否是数组,还可以用原型链的方法:
1 | var isArray = function( obj ) { |
方法
array.concat(item1[, item2, item2, ...])
concat
产生一个新数组,参数item
可以是一个任意类型的值,也可以是一个数组,如果是数组,那么数组的所有元素都会被添加到新数组里。1
2
3var a = ['a','b'];
var b = ['x','y'];
a.concat(b, true); // ["a", "b", "x", "y", true]array.join(separator)
join
方法把array
中的每个元素构造成一个字符串,接着用一个separator
分隔符把它们连接在一起。默认的separator
是逗号,。想要无间隔的连接,可以使用空字符串。1
2
3var a = ['a', 'b', 'c'];
a.join(); // 'a,b,c'
a.join(''); // 'abc'如果想把大量的字符串片段组装成一个字符串,用 `+` 元素运算符连接这些片段会比把这些片段放到一个数组中并且用 `join` 连接起来更快。array.pop()
pop
方法移除数组中的最后一个元素并返回该元素。如果array
是空值,则会返回undefined
1
2
3
4
5
6var a = ['a', 'b', 'c'];
a.pop(); // 'c'
// pop可以这样实现:
Array.method('pop', function() {
return this.splice( this.length - 1, 1 )[0];
});array.push(item1[, item2, ...])
push
方法把一个或多个参数附加到一个数组的尾部。参数可以是任何类型的值,也可以是数组。如果是数组,它会把参数数组作为这个元素添加到数组中。返回修改后的数组长度。1
2
3
4
5
6
7
8
9
10
11
12
13var a = ['a', 'b', 'c'];
var b = ['x', 'y', 'z'];
var c = a.push(b, true);
// a: ["a", "b", "c", ['x', 'y', 'z'], true]
// c: 5
// push可以这样实现:
Array.method('push', function() {
this.splice.apply(
this,
[this.length, 0].
concat(Array.prototype.slice.apply(arguments)));
return this.length;
});array.reverse()
reverse
方法反转array
里的元素的顺序,并返回array
本身。1
2var a = ['a', 'b', 'c'];
var b = a.reverse(); // a和b都是['c', 'b', 'a']array.shift()
shift
方法移除数组中的第一个元素,并且返回这个元素。如果数组为空,则返回undefined
。shift
通常比pop
慢得多。1
2
3
4
5
6var a = ['a', 'b', 'c'];
var b = a.shift(); // a: ['b', 'c'], b: 'a'
// shift实现
Array.method('shift', function() {
return this.splice(0, 1)[0];
});array.slice(start, end)
slice
方法对数组进行一段浅复制。复制从下标start
到end
结束。end
下标默认是array.length
。如果两个参数任意一个是负数,那么end
数值会是和array.length
相加之后的值。如果start
大于array.length
,则返回一个空数组。1
2
3
4var a = ['a', 'b', 'c'];
var b = a.slice(0, 1); // ['a']
var c = a.slice(1); // ['b', 'c']
var d = a.slice(-1); // ['c']array.sort(comparefn)
sort
方法对array
里的所有元素进行排序,默认的比较函数是把被排序的元素都视为字符串。所以它不能正确地给一组数字进行排序:1
2var n = [4, 8, 15, 16, 23, 42];
n.sort(); // [15, 16, 23, 4, 42, 8]幸运的是你可以使用自定义的比较函数来使得一组数字能正常排序,比较函数接受两个参数,如果他们相等,则返回0,如果第一个参数应该排序在前面,则返回负数,如果第二个参数应该排在前面,则返回一个正数。
1
2
3n.sort(function(a, b) {
return a - b;
}); // [4, 8, 15, 16, 23, 42]如果想给包含任何简单值的数组进行排序,可以这样:
1
2
3
4
5
6
7
8
9
10var m = ['aa', 'bb', 'a', 5, 3, 10];
m.sort(function(a, b) {
if (a === b) {
return 0;
}
if (typeof a === typeof b) {
return a < b ? -1 : 1;
}
return typeof a < typeof b ? -1 : 1;
}); // [3, 5, 10, 'a', 'aa', 'bb']array.splice(start, deleteCount, item...)
splice
方法从array
中移除一个或多个元素,并用新的item
替换它们。start
是移除元素的起始位置,deleteCount
是移除个数。如果有额外的参数,则item
会插入到被移除的元素的位置上。返回一个包含被移除元素的数组。1
2var a = ['a', 'b', 'c'];
var r = a.splice(1, 1, 'ache', 'bug'); // a: ['a', 'ache', 'bug', 'c'], r: ['b']array.unshift(item...)
unshift
方法是把item
插入到数组的开始部分。返回新数组的length
。1
2var a = ['a', 'b', 'c'];
var r = a.unshift('#', '$'); // a: ['#', '$', 'a', 'b', 'c'], r: 5