将类数组对象转换为数组

什么是类似数组的对象?

JavaScript 具有类似数组的对象,它是具有 length 属性的数组的 Object 表示。例如:

var realArray = ['a', 'b', 'c'];
var arrayLike = {
  0: 'a',
  1: 'b',
  2: 'c',
  length: 3
};

类似数组的对象的常见示例是函数中的 arguments 对象以及从 document.getElementsByTagNamedocument.querySelectorAll 等方法返回的 HTMLCollectionNodeList 对象。

但是,Arrays 和类似 Array 的对象之间的一个关键区别是,类似于 Array 的对象继承自 Object.prototype 而不是 Array.prototype 。这意味着类似数组的对象无法访问常见的数组原型方法,forEach()push()map()filter()slice()

var parent = document.getElementById('myDropdown');
var desiredOption = parent.querySelector('option[value="desired"]');
var domList = parent.children;

domList.indexOf(desiredOption); // Error! indexOf is not defined.
domList.forEach(function() { 
  arguments.map(/* Stuff here */) // Error! map is not defined.
}); // Error! forEach is not defined.

function func() {
  console.log(arguments);
}
func(1, 2, 3);   // → [1, 2, 3]

在 ES6 中将类似数组的对象转换为数组

  1. Array.from

Version >= 6

const arrayLike = {
  0: 'Value 0',
  1: 'Value 1',
  length: 2
};
arrayLike.forEach(value => {/* Do something */}); // Errors
const realArray = Array.from(arrayLike);
realArray.forEach(value => {/* Do something */}); // Works
  1. for...of

Version >= 6

var realArray = [];
for(const element of arrayLike) {
  realArray.append(element);
}
  1. 传播运算符:

Version >= 6

[...arrayLike]
  1. Object.values

Version >= 7

var realArray = Object.values(arrayLike);
  1. Object.keys

Version >= 6

var realArray = Object
   .keys(arrayLike)
   .map((key) => arrayLike[key]);

在≤ES5 中将类数组对象转换为数组

像这样使用 Array.prototype.slice

var arrayLike = {
  0: 'Value 0',
  1: 'Value 1',
  length: 2
};
var realArray = Array.prototype.slice.call(arrayLike);
realArray = [].slice.call(arrayLike); // Shorter version

realArray.indexOf('Value 1'); // Wow! this works

你也可以使用 Function.prototype.call 直接在类似数组的对象上调用 Array.prototype 方法,而无需转换它们:

Version >= 5.1

var domList = document.querySelectorAll('#myDropdown option');

domList.forEach(function() { 
  // Do stuff
}); // Error! forEach is not defined.

Array.prototype.forEach.call(domList, function() { 
  // Do stuff
}); // Wow! this works

你也可以使用 [].method.bind( arrayLikeObject ) 借用数组方法并将它们放到你的对象上:

Version >= 5.1

var arrayLike = {
  0: 'Value 0',
  1: 'Value 1',
  length: 2
};

arrayLike.forEach(function() {
  // Do stuff
}); // Error! forEach is not defined.

[].forEach.bind(arrayLike)(function(val){
  // Do stuff with val
}); // Wow! this works

转换期间修改项目

在 ES6 中,在使用 Array.from 时,我们可以指定一个 map 函数,该函数返回正在创建的新数组的映射值。

Version >= 6

Array.from(domList, element => element.tagName); // Creates an array of tagName's

有关详细分析,请参阅阵列是对象