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 ]