JavaScript中存在有一種類數組,或者說僞數組。常常見到的僞數組有函數的arguments
對象、dom.querySelectorAll
等獲取的NodeList
類(NodeList
自己具備forEach
方法)等。數組
僞數組並非數組,它沒有繼承Array.prototype
,可是它「看起來像數組」,它自己沒有數組的標準方法,可是它能夠複用這些標準方法。dom
function arrayLike() { arguments.forEach(a => console.log(a));//TypeError: arguments.forEach is not a function } arrayLike(1, 2, 3);
如上例所示,arguments
對象自己並無forEach
方法,可是它能夠複用數組的這些標準方法。函數
function arrayLike() { // arguments.forEach(a => console.log(a)); [].forEach.call(arguments, a => console.log(a));// 1 2 3 經過call改變this指向,調用數組的方法 [...arguments].forEach(a => console.log(a));// 1 2 3 構建一個真實數組,而後調用數組的方法 } arrayLike(1, 2, 3);
一個數組對象必然具備兩個特色:this
因此很簡單,只要實現這兩個特色,一個對象就是僞數組對象了。prototype
const arr = { 1: 'AAA', 3: 'CCC', length: 8, }; [].forEach.call(arr, (item, i) => console.log(item, i)); //AAA 1 CCC 3
concat
方法對於數組和僞數組,在數組的標準方法中,只有concat
方法是不通用的,對於一個僞數組,concat
方法會將其做爲一個總體鏈接起來。code
console.log([].concat.call(arr, [7, 8]));//[ { '1': 'AAA', '3': 'CCC', length: 8 }, 7, 8 ] console.log([1, 2].concat([7, 8]));//[ 1, 2, 7, 8 ]
上例展現了數組和僞數組調用concat
的不一樣結果,在遇到這種狀況時,咱們只有本身對僞數組進行轉換,好比:對象
1.經過slice方法,複製僞數組繼承
console.log([].concat.call([].slice.call(arr), [7, 8])); //[ <1 empty item>, 'AAA', <1 empty item>, 'CCC', <4 empty items>, 7, 8 ]
2.經過Symbol.isConcatSpreadable
改變對僞數組對象進行concat
操做時的默認行爲索引
const arr = { 1: 'AAA', 3: 'CCC', length: 8, [Symbol.isConcatSpreadable]: true, }; console.log([].concat.call(arr, [7, 8])); //[ <1 empty item>, 'AAA', <1 empty item>, 'CCC', <4 empty items>, 7, 8 ]