为什么 [array].concat() 和 [array].concat.apply() 给出不同的输出

Why [array].concat() and [array].concat.apply() gives different output ?

本文关键字:concat array 输出 为什么 apply      更新时间:2023-09-26

下面的代码,

console.log([].concat.apply([2],[[99],5,6,[2,3]]));

输出

[ 2, 99, 5, 6, 2, 3 ]

而下面的代码,

console.log([2].concat([99]).concat([5,6,[2,3]]));

输出

[ 2, 99, 5, 6, [ 2, 3 ] ]

我的假设是

console.log([].concat.apply([2],[[99],5,6,[2,3]]));

应该是

[2,[99],5,6,[2,3]]

但不是,为什么?

那是因为:

console.log( [].concat.apply([2],[[99],5,6,[2,3]]) );

相当于:

console.log( [2].concat([99], 5, 6, [2,3]) );

.concat 采用多个参数,并将所有数组(和非数组参数(合并到单个数组中。基本上,数组参数解压缩 1 级。

要获得该输出,您必须将每个数组元素包装在一个额外的数组中。

console.log( [].concat.apply([2],[[[99]],5,6,[[2,3]]]) );

也许您更愿意使用基于.push的方法。

var a = [2];
a.push.apply(a, [[99],5,6,[2,3]]);
console.log(a);

你以某种方式假设没有看到文档。看,concat 的实际语法是,

Array.prototype.concat ( [ item1 [ , item2 [ , … ] ] ] )

所以你的代码勉强等于,

[].concat.apply([itm1], [itm2,itm3,itm4]...)

从代码的角度来看,您的代码类似于,

[2].concat([99],5,6,[2,3]);

让我们拆解你的代码,

console.log([].concat.apply([2],[[99],5,6,[2,3]]));
// 1. apply will call the function by applying the parameter supplied as an array.
// 2. so the first parameter for apply would be this for that function
// 3. and the second parameter for it would be the arguments in an array form.
// 4. Hence internally apply will call the function concat as,
//    [2].concat([99],5,6,[2,3]); //[2] will be 'this'

但是对于您的要求,您不需要使用apply,您可以使用call

console.log([].concat.call([2],[[99],5,6,[2,3]]));
//[2,[99],5,6,[2,3]]

注意,apply实际上是第二个参数的扩展运算符。 所以

相同的结果:

console.log([].concat.apply([2],[[99],5,6,[2,3]]));

console.log([2].concat(...[[99],5,6,[2,3]])); // * using es6 spread operator `...`

console.log([2].concat([99],5,6,[2,3]));

这与以下不同:

console.log([2].concat([[99],5,6,[2,3]]));

区别在于点差。

如果你参考 concat MDN,你会发现 Array.prototype.concat 的语法是

var new_array = old_array.concat(value1[, value2[, ...[, valueN]]])

而不仅仅是价值观。要连接成新数组的数组和/或值

所以[].concat.apply([],[2,3,[6,4]])等于[].concat.apply([],[2,3,6,4]).