Array

和其他强制类型的语言相比,JavaScript 的 array 只是值的容器,而这些值可以是任何类型:string 或者 number 或者 object,甚至是另一个 array(这也是你得到多维数组的方法)。

  1. var a = [ 1, "2", [3] ];
  2. a.length; // 3
  3. a[0] === 1; // true
  4. a[2][0] === 3; // true

你不需要预先指定 array 的大小,你可以仅声明它们并加入你觉得合适的值:

  1. var a = [ ];
  2. a.length; // 0
  3. a[0] = 1;
  4. a[1] = "2";
  5. a[2] = [ 3 ];
  6. a.length; // 3

警告: 在一个 array 值上使用 delete 将会从这个 array 上移除一个值槽,但就算你移除了最后一个元素,它也 不会 更新 length 属性,所以多加小心!我们会在第五章讨论 delete 操作符的更多细节。

要小心创建“稀散”的 array(留下或创建空的/丢失的值槽):

  1. var a = [ ];
  2. a[0] = 1;
  3. // 这里没有设置值槽 `a[1]`
  4. a[2] = [ 3 ];
  5. a[1]; // undefined
  6. a.length; // 3

虽然这可以工作,但你留下的“空值槽”可能会导致一些令人困惑的行为。虽然这样的值槽看起来拥有 undefined 值,但是它不会像被明确设置(a[1] = undefined)的值槽那样动作。更多信息可以参见第三章的“Array”。

array 是被数字索引的(正如你所想的那样),但微妙的是它们也是对象,可以在它们上面添加 string 键/属性(但是这些属性不会计算在 arraylength 中):

  1. var a = [ ];
  2. a[0] = 1;
  3. a["foobar"] = 2;
  4. a.length; // 1
  5. a["foobar"]; // 2
  6. a.foobar; // 2

然而,一个需要小心的坑是,如果一个可以被强制转换为10进制 numberstring 值被用作键的话,它会认为你想使用 number 索引而不是一个 string 键!

  1. var a = [ ];
  2. a["13"] = 42;
  3. a.length; // 14

一般来说,向 array 添加 string 键/属性不是一个好主意。最好使用 object 来持有键/属性形式的值,而将 array 专用于严格地数字索引的值。

类 Array

偶尔你需要将一个类 array 值(一个数字索引的值的集合)转换为一个真正的 array,通常你可以对这些值的集合调用数组的工具函数(比如 indexOf(..)concat(..)forEach(..) 等等)。

举个例子,各种 DOM 查询操作会返回一个 DOM 元素的列表,对于我们转换的目的来说,这些列表不是真正的 array 但是也足够类似 array。另一个常见的例子是,函数为了像列表一样访问它的参数值,而暴露了 arugumens 对象(类 array,在 ES6 中被废弃了)。

一个进行这种转换的很常见的方法是对这个值借用 slice(..) 工具:

  1. function foo() {
  2. var arr = Array.prototype.slice.call( arguments );
  3. arr.push( "bam" );
  4. console.log( arr );
  5. }
  6. foo( "bar", "baz" ); // ["bar","baz","bam"]

如果 slice() 没有用其他额外的参数调用,就像上面的代码段那样,它的参数的默认值会使它具有复制这个 array(或者,在这个例子中,是一个类 array)的效果。

在 ES6 中,还有一种称为 Array.from(..) 的内建工具可以执行相同的任务:

  1. ...
  2. var arr = Array.from( arguments );
  3. ...

注意: Array.from(..) 拥有其他几种强大的能力,我们将在本系列的 ES6 与未来 中涵盖它的细节。