JavaScript中,数组是一个特殊的对象,其property名为正整数,且其length属性会随着数组成员的增减而发生变化,同时又从Array构造函数中继承了一些用于进行数组操作的方法。
而对于一个普通的对象来说,如果它的所有property名均为正整数,同时也有相应的 length 属性,那么虽然该对象并不是由Array构造函数所创建的,它依然呈现出数组的行为,在这种情况下,这些对象被称为 “类数组对象” 。
var o = {0:42,1:52,2:63,length:3}
console.log(o); // 返回:{0: 42, 1: 52, 2: 63, length: 3}
console.log(o.length); // 返回3
与普通对象不同的是,类数组对象拥有一个特性:可以在类数组对象上应用数组的操作方法。比如,在ECMAScript 5标准中,可以用以下方法来将上面的对象o合并成字符串:
var o = {0:42,1:52,2:63,length:3}
console.log(Array.prototype.join.call(o));// “42,52,63”
将类数组对象转换成普通数组,下面分别介绍两种方法:
法一: 可以使用 Array.prototype.slice.call() 方法。
// ES5的写法
var o = {0:42,1:52,2:63,length:3}
console.log(Array.prototype.slice.call(o)); // [42, 52, 63]
法二: Array.from
方法用于将两类对象转为真正的数组:类似数组的对象(array-like object)和可遍历(iterable)的对象(包括ES6新增的数据结构Set和Map)。
// ES6的写法
var o = {0:42,1:52,2:63,length:3}
console.log(Array.from(o)) // [42,52,63]
在浏览器环境中,document.getElementsByTagName()语句返回的就是一个类数组对象。在function调用中,function代码内的arguments变量(保存传入的参数)也是一个类数组对象。
在ECMAScript 5标准中,字符串string就是一个只读的类数组对象:
var s = "History";
console.log(s[3]); // t
console.log(s.length) // 7
console.log(Array.prototype.join.call(s, " ")); // H i s t o r y
扩展运算符(...
)也可以将某些数据结构转为数组。扩展运算符背后调用的是遍历器接口(Symbol.iterator
),如果一个对象没有部署这个接口,就无法转换。Array.from
方法还支持类似数组的对象。所谓类似数组的对象,本质特征只有一点,即必须有length
属性。因此,任何有length
属性的对象,都可以通过Array.from
方法转为数组,而此时扩展运算符就无法转换。
Array.from({ length: 3 }); // [ undefined, undefined, undefined ]
上面代码中,Array.from
返回了一个具有三个成员的数组,每个位置的值都是undefined
。扩展运算符转换不了这个对象。
Array.from()
可以将各种值转为真正的数组,并且还提供map
功能。这实际上意味着,只要有一个原始的数据结构,你就可以先对它的值进行处理,然后转成规范的数组结构,进而就可以使用数量众多的数组方法。
Array.from({ length: 2 }, () => 'jack') // ['jack', 'jack']