类数组的定义以及类数组转换为数组的方法

174 阅读1分钟

类数组又被成为“伪数组”,因为并不是真正的数组,只是类似于数组而已,类数组具有以下特点:

  • 拥有 length 属性
  • 可以使用下标方式访问
  • 但不能调用数组的方法

常见的类数组有以下四种:

  • 字符串(是类数组,但不是类数组对象,下面三种都是类数组对象)
  • 函数的 arguments
  • DOM 的 NodeList
  • 一个函数也可以被看作是类数组对象,因为它含有 length 属性值,代表可接收的参数个数

常见的类数组转换为数组的方法:

1、通过 call 或 apply 调用数组的 slice 方法来实现转换

Array.prototype.slice.call(arrayLike);   // (推荐)
Array.prototype.slice.apply(arrayLike);

// 或者
[].slice.call(arrayLike)

2、通过 call 调用数组的 splice 方法来实现转换(不推荐,会改变原数组)

Array.prototype.splice.call(arrayLike, 0);

3、通过 apply 调用数组的 concat 方法来实现转换(字符串不可以)

Array.prototype.concat.apply([], arrayLike);

4、通过 Array.from 方法来实现转换(ES6新增)

Array.from(arrayLike);

5、展开运算符(ES6新增)

[...arrayLike];

【注意】 扩展运算符背后调⽤的是遍历器接⼝( Symbol.iterator ),如果⼀个对象没有部署这个接⼝,就⽆法转换。比如:

let arrayLike = {0:42, 1:52, 2:63, length:3}
[...arrayLike]   // 报错 TypeError: Invalid attempt to spread non-iterable instance.

附:为类数组部署 Iterator 接⼝

方式1let arrayLike = {
  0:42, 
  1:52, 
  2:63, 
  length:3, 
  [Symbol.iterator]: Array.prototype[Symbol.iterator]
};
[...arrayLike]   // [42, 52, 63]

⽅式2:
NodeList.prototype[Symbol.iterator]= Array.prototype[Symbol.iterator]; 
// 或者
NodeList.prototype[Symbol.iterator]=[][Symbol.iterator];
[...document.querySelectorAll('div')]   // 正常执⾏

6、$.makeArray()(字符串不可以)

JQ 中的内置⽅法;对类数组的对象有效。

$.makeArray( arrayLike )

7、for···of

【注意】  该方式背后调⽤的也是遍历器接⼝( Symbol.iterator )。

let arrayLike = {
  0:42, 
  1:52, 
  2:63, 
  length:3, 
  [Symbol.iterator]: Array.prototype[Symbol.iterator]
};

let array = [];

for (const arrayLikeElement of arrayLike) {
  array.push(arrayLikeElement)
}

console.log(array)   // [42, 52, 63]