数组字面量

和JavaScript中大多数“东西”一样,数组也是对象。可以通过内置构造函数Array()来创建数组,也可以通过字面量形式创建,就像对象字面量那样。而且更推荐使用字面量创建数组。

这里的示例代码给出了创建两个具有相同元素的数组的两种方法,使用Array()和使用字面量模式:

  1. // 有三个元素的数组
  2. // 注意:这是反模式
  3. var a = new Array("itsy", "bitsy", "spider");
  4. // 完全相同的数组
  5. var a = ["itsy", "bitsy", "spider"];
  6. console.log(typeof a); // "object",因为数组也是对象
  7. console.log(a.constructor === Array); // true

数组字面量语法

数组字面量写法非常简单:整个数组使用方括号括起来,数组元素之间使用逗号分隔。数组元素可以是任意类型,包括数组和对象。

数组字面量语法简单直观而且优雅,毕竟数组只是从0开始索引的一些值的集合,完全没必要引入构造器和new运算符(还要写更多的代码)。

Array()构造函数的“陷阱”

我们对new Array()敬而远之还有一个原因,就是为了避免构造函数带来的陷阱。

如果给Array()构造函数传入一个数字,这个数字并不会成为数组的第一个元素,而是设置了数组的长度。也就是说,new Array(3)创建了一个长度为3的数组,而不是某个元素是3。如果你访问数组的任意元素都会得到undefined,因为元素并不存在。下面的示例代码展示了字面量和构造函数的区别:

  1. // 含有1个元素的数组
  2. var a = [3];
  3. console.log(a.length); // 1
  4. console.log(a[0]); // 3
  5. // 含有3个元素的数组
  6. var a = new Array(3);
  7. console.log(a.length); // 3
  8. console.log(typeof a[0]); // "undefined"

构造函数的行为可能有一点出乎意料,但当给new Array()传入一个浮点数时情况就更糟糕了,这时会出错(译注:给new Array()传入浮点数会报“范围错误”RangError),因为数组长度不可能是浮点数。

  1. // 使用数组字面量
  2. var a = [3.14];
  3. console.log(a[0]); // 3.14
  4. var a = new Array(3.14); // RangeError: invalid array length
  5. console.log(typeof a); // "undefined"

为了避免在运行时动态创建数组时出现这种错误,强烈推荐使用数组字面量来代替new Array()

有些人用Array()构造器来做一些有意思的事情,比如用来生成重复字符串。下面这行代码返回的字符串包含255个空格(请读者思考为什么不是256个空格)。var white = new Array(256).join(' ');

检查是否数组

如果typeof的操作数是数组的话,将返回“object”。

  1. console.log(typeof [1, 2]); // "object"

这个结果勉强说得过去,毕竟数组也是一种对象,但对我们来说这个结果却没什么用,实际上你往往是需要知道一个值是不是真正的数组。有时候你会见到一些检查数组的方法:检查length属性、检查数组方法比如slice()等等,但这些方法非常脆弱,非数组的对象也可以拥有这些同名的属性。还有些人使用instanceof Array来判断数组,但这种方法在某些版本的IE里的多个iframe的场景中会出问题(译注:原因就是在不同iframe中创建的数组不会相互共享其prototype属性)。

ECMAScript5定义了一个新的方法Array.isArray(),如果参数是数组的话就返回true。比如:

  1. Array.isArray([]); // true
  2. // 尝试用一个类似数组的对象去测试
  3. Array.isArray({
  4. length: 1,
  5. "0": 1,
  6. slice: function () {}
  7. }); // false

如果你的开发环境不支持ECMAScript5,可以通过Object.prototype.toString()方法来代替。如调用toStringcall()方法并传入数组上下文,将返回字符串“[object Array]”。如果传入对象上下文,则返回字符串“[object Object]”。因此可以这样做:

  1. if (typeof Array.isArray === "undefined") {
  2. Array.isArray = function (arg) {
  3. return Object.prototype.toString.call(arg) === "[object Array]";
  4. };
  5. }