將類陣列物件轉換為陣列

什麼是類似陣列的物件?

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

有關詳細分析,請參閱陣列是物件