第二章:值 - Arrays
Array
和其他强制类型的语言相比,JavaScript 的 array
只是值的容器,而这些值可以是任何类型:string
或者 number
或者 object
,甚至是另一个 array
(这也是你得到多维数组的方法)。
var a = [ 1, "2", [3] ];
a.length; // 3
a[0] === 1; // true
a[2][0] === 3; // true
你不需要预先指定 array
的大小,你可以仅声明它们并加入你觉得合适的值:
var a = [ ];
a.length; // 0
a[0] = 1;
a[1] = "2";
a[2] = [ 3 ];
a.length; // 3
警告: 在一个 array
值上使用 delete
将会从这个 array
上移除一个值槽,但就算你移除了最后一个元素,它也 不会 更新 length
属性,所以多加小心!我们会在第五章讨论 delete
操作符的更多细节。
要小心创建“稀散”的 array
(留下或创建空的/丢失的值槽):
var a = [ ];
a[0] = 1;
// 这里没有设置值槽 `a[1]`
a[2] = [ 3 ];
a[1]; // undefined
a.length; // 3
虽然这可以工作,但你留下的“空值槽”可能会导致一些令人困惑的行为。虽然这样的值槽看起来拥有 undefined
值,但是它不会像被明确设置(a[1] = undefined
)的值槽那样动作。更多信息可以参见第三章的“Array”。
array
是被数字索引的(正如你所想的那样),但微妙的是它们也是对象,可以在它们上面添加 string
键/属性(但是这些属性不会计算在 array
的 length
中):
var a = [ ];
a[0] = 1;
a["foobar"] = 2;
a.length; // 1
a["foobar"]; // 2
a.foobar; // 2
然而,一个需要小心的坑是,如果一个可以被强制转换为10进制 number
的 string
值被用作键的话,它会认为你想使用 number
索引而不是一个 string
键!
var a = [ ];
a["13"] = 42;
a.length; // 14
一般来说,向 array
添加 string
键/属性不是一个好主意。最好使用 object
来持有键/属性形式的值,而将 array
专用于严格地数字索引的值。
类 Array
偶尔你需要将一个类 array
值(一个数字索引的值的集合)转换为一个真正的 array
,通常你可以对这些值的集合调用数组的工具函数(比如 indexOf(..)
、concat(..)
、forEach(..)
等等)。
举个例子,各种 DOM 查询操作会返回一个 DOM 元素的列表,对于我们转换的目的来说,这些列表不是真正的 array
但是也足够类似 array
。另一个常见的例子是,函数为了像列表一样访问它的参数值,而暴露了 arugumens
对象(类 array
,在 ES6 中被废弃了)。
一个进行这种转换的很常见的方法是对这个值借用 slice(..)
工具:
function foo() {
var arr = Array.prototype.slice.call( arguments );
arr.push( "bam" );
console.log( arr );
}
foo( "bar", "baz" ); // ["bar","baz","bam"]
如果 slice()
没有用其他额外的参数调用,就像上面的代码段那样,它的参数的默认值会使它具有复制这个 array
(或者,在这个例子中,是一个类 array
)的效果。
在 ES6 中,还有一种称为 Array.from(..)
的内建工具可以执行相同的任务:
...
var arr = Array.from( arguments );
...
注意: Array.from(..)
拥有其他几种强大的能力,我们将在本系列的 ES6 与未来 中涵盖它的细节。