2016-11-11 96 views
13

使用Array.from(document.querySelectorAll('div'))還是[...document.querySelectorAll('div')]有什麼區別?Array.from()vs spread syntax

這裏是一個例子:

let spreadDivArray = [...document.querySelectorAll('div')]; 
console.log(spreadDivArray); 

let divArrayFrom = Array.from(document.querySelectorAll('div')); 
console.log(divArrayFrom); 

console.log()的將記錄相同的結果。

是否有任何性能差異?

+0

擴展運算符的好處是它支持'Object'。 performance .. idk –

+0

要了解是否有任何性能差異,請運行基準測試。根據您是在本地ES6環境還是轉換到ES5,結果可能會有很大不同。 – 2016-11-11 12:46:08

+6

主要區別在於'Array.from'可以處理沒有實現迭代器協議(即Symbol.iterator)的類似數組的對象。即使使用ES6和新的瀏覽器規格,這些規格也越來越少。 – nils

回答

1

區別在於擴展允許數組爲擴展。而from()創建了一個新的陣列。 .from()不會擴展任何內容,它會根據提供的數據創建一個新數組;另一方面,擴展運算符可以擴展具有新屬性的數組。

+4

好吧,數組文字總是創建* new *數組... – Bergi

+2

我不確定是否我只是誤解你的措辭,但你是否建議spread運算符改變數組而不是創建一個新的數組? – Bergi

+0

@Bergi擴散算子不會創建數組。 OP示例中的數組創建是通過擴展運算符周圍的方括號完成的。 –

-1

使用Babel是一種很好的方法來查看內部發生了什麼。儘管如此,我們還是想請教一下。確保Babel中選擇了最新版本,因爲默認設置是錯誤的。

使用上面的示例,這是輸出。

function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } 

var spreadDivArray = [].concat(_toConsumableArray(document.querySelectorAll('div'))); 
console.log(spreadDivArray); 

var divArrayFrom = Array.from(document.querySelectorAll('div')); 
console.log(divArrayFrom); 
+2

如果節點列表不是可擴展的,'[] .concat'似乎不起作用?這是一個Babel輸出嗎? – Bergi

+0

'這是一個Babel輸出嗎?的確,我只是將代碼複製到了babeljs.io,你有沒有一個例子呢?也許babel會在需要時進行其他轉換。這當然只是針對這個特定的情況進行測試。 – Keith

+2

babeljs.io repl有一些奇怪的選項,它不是很可靠。使用'[] .concat'是不正確的簡化(對數組參數的擴展語法只做相同的處理),這可能是由於Babel中的錯誤或未知設置造成的。 – Bergi

5

那麼,Array.from是一個靜態方法,即,而spread語法的功能是數組文本語法的一部分。你可以像數據一樣傳遞函數,你可以調用它們一次,幾次或根本不調用它們。這在spread語法中是不可能的,在這方面它是靜態的。

@nils已經指出的另一個區別是,Array.from也適用於類似數組的對象,它們沒有實現可迭代協議。 spread另一方面需要迭代。

+0

「Array.from也適用於類似數組的對象,它不會實現可迭代協議」 - 您能給出一個這樣的對象的例子嗎? – mpen

+0

沒關係,[Michał舉了一個例子](https://stackoverflow.com/a/40549565/65387)。 – mpen

8

傳播元件it's not an operator)僅適用於那些對象iterable(即實現@@iterator方法)。 Array.from()也適用於類似數組的對象(即具有length屬性和索引元素的對象),這些對象不可迭代。看到這個例子:

const arrayLikeObject = { 0: 'a', 1: 'b', length: 2 }; 
 

 
// This logs ['a', 'b'] 
 
console.log(Array.from(arrayLikeObject)); 
 
// This throws TypeError: arrayLikeObject[Symbol.iterator] is not a function 
 
console.log([...arrayLikeObject]);

另外,如果你只是想的東西轉換成陣,我認爲這是更好地使用Array.from(),因爲它更具有可讀性。例如,當你想連接多個數組時,擴展元素很有用(['a', 'b', ...someArray, ...someOtherArray])。

+0

雖然我同意'Array.from()'是一個非常可讀的方式來實現這一點,我覺得傳播元素語法'... arrayLikeObject'就像人們可讀(或更多)。 – qarthandso