数组字面量

数组字面量提供了一种非常方便的创建数组的方法。一个数组表达式是在一对方括号内包围零个或多个用逗号分隔的值的表达式。
数组的第一个值的属性名是’0’。

1
2
3
4
5
6
7
8
var empty = [];
var numbers = ['zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven'];
empty[1]; // undefined
numbers[1]; // 'one'
empty.length; // 0
numbers.length; // 8

在大多数语言中,一个数组的所有元素都要求是相同的类型。js允许数组包含任意混合类型的值:

1
2
var misc = ['string', 98.6, true, false, null];
misc.length; // 5

长度

每个数组都有一个length属性。和大多数的语言不同,js中数组的length是没有上限的。如果用大于或等于length的数字作为下标来存储一个元素,那么length的值会被增大以便容纳新的值,不会发生数组越界的错误。可以直接设置length的值,如果length大于当前的length值,则更大的那些下标的值都是’undefined’;如果更小,
那么将会把所有下标大于等于新length的属性给删除。通过把下标指定为一个数组的当前length,可以附加一个新元素到该数组的末尾。

1
2
3
4
5
6
7
var arr = ['one', 'two', 'three'];
arr.length; // 3
arr.length = 6;
arr; // ['one', 'two', 'three', undefined, undefined, undefined]
arr.length = 2;
arr; // ['one', 'two']
arr[arr.length] = 'last'; // ['one', 'two', 'last'];

删除

由于js的数组其实就是对象,所以delete运算符可以删除数组的元素:

1
2
3
var arr = ['one', 'two', 'three'];
delete arr[1];
arr; // ['one', undefined, 'three']

遗憾的是删除后的数组直接留了一个空位值是undefined,幸运的是可以通过数组的splice方法来进行调整。splice方法接受2个参数,第一个是数组的序号,第二个是删除的元素个数,并且返回一个数组,这个数组包含了所有的删除元素。

1
2
arr.splice(1, 1); // [undefined]
arr; // ['one', 'three']

枚举

因为js数组其实就是对象,所以for in语句可以用来遍历一个数组的所有属性。但是用for in语句无法保证顺序。所以遍历还是用常规的for循环

1
2
3
4
var numbers = [1, 2, 3, 4, 5];
for ( var i = 0, l = numbers.length; i < l; i++ ) {
console.log( numbers[i] ); // 1, 2, 3, 4, 5
}

判断是否是数组

1
typeof [1, 2, 3]; // 'object'

js本身对于数组和对象的区别是混乱的。typeof运算符报告数组的类型是object,没有任何意义。
js没有一个好的机制来区别是数组还是对象,但是我们可以自己实现一个is_array函数来弥补这个缺陷:

1
2
3
4
5
var isArray = function( obj ) {
return obj &&
typeof obj === 'object' &&
obj.constructor === Array;
};

上面这个判断基本在常规页面就能很好的区分出数组还是对象了。但是也有特例,比如在不同的窗口(window)或帧(frame)就会失败。这个时候可以用下面这个替换:

1
2
3
var isArray = function( obj ) {
return Object.prototype.toString.apply( obj ) === '[object Array]';
};

判断某个对象是否是数组,还可以用原型链的方法:

1
2
3
var isArray = function( obj ) {
return obj.__prototype__ === Array.prototype;
}

方法

  • array.concat(item1[, item2, item2, ...])
    concat产生一个新数组,参数item可以是一个任意类型的值,也可以是一个数组,如果是数组,那么数组的所有元素都会被添加到新数组里。

    1
    2
    3
    var 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
    3
    var a = ['a', 'b', 'c'];
    a.join(); // 'a,b,c'
    a.join(''); // 'abc'

    如果想把大量的字符串片段组装成一个字符串,用+元素运算符连接这些片段会比把这些片段放到一个数组中并且用join连接起来更快。
  • array.pop()
    pop方法移除数组中的最后一个元素并返回该元素。如果array是空值,则会返回undefined

    1
    2
    3
    4
    5
    6
    var 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
    13
    14
    var 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
    2
    var a = ['a', 'b', 'c'];
    var b = a.reverse(); // a和b都是['c', 'b', 'a']
  • array.shift()
    shift方法移除数组中的第一个元素,并且返回这个元素。如果数组为空,则返回undefined。shift通常比pop慢得多。

    1
    2
    3
    4
    5
    6
    var 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
    4
    var 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
    2
    var n = [4, 8, 15, 16, 23, 42];
    n.sort(); // [15, 16, 23, 4, 42, 8]

    幸运的是你可以使用自定义的比较函数来使得一组数字能正常排序,比较函数接受两个参数,如果他们相等,则返回0,如果第一个参数应该排序在前面,则返回负数,如果第二个参数应该排在前面,则返回一个正数。

    1
    2
    3
    n.sort(function(a, b) {
    return a - b;
    }); // [4, 8, 15, 16, 23, 42]

    如果想给包含任何简单值的数组进行排序,可以这样:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    var 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
    2
    var 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
    2
    var a = ['a', 'b', 'c'];
    var r = a.unshift('#', '$'); // a: ['#', '$', 'a', 'b', 'c'], r: 5