这两个作业之间有什么区别?
this.list.push(...response.data);
//vs
this.list = [].concat(this.list, response.data);
答案 0 :(得分:5)
结果将为内容相同。
response.data
中包含的项目将附加到this.list
之后。
但是,对于this.list.push(...response.data)
,列表保持不变,并且只是使用新项进行了扩展,因此该列表被修改了。任何对该列表的引用都会看到更改的发生。
使用[].concat(this.list, response.data)
,将创建一个新列表。这个新列表是两个列表的串联,然后被重新分配给this.list
。因此,分配后this.list
指向一个新列表。在这种情况下,任何对旧列表的引用都不会看到更改。
答案 1 :(得分:5)
第一个示例:
this.list.push(...response.data);
该示例使用push
对数据进行突变。这意味着该数组已更改到位。这被视为“不纯” ,因为它不会返回 new 对象-它会更改已经存在的数据。
第二个示例:
this.list = [].concat(this.list, response.data);
此示例返回一个 new 数组对象。这意味着它订阅了功能范式。之所以认为它是纯,是因为它不会更改现有的Array,而是会为此创建一个新的数组。
现在您可能会想“ 这就是其他答案所说的! ”
您是对的。起初我只是要编写一个附录,但我想我也可以简洁地提供所有信息。答案的第一部分看起来像是在重复练习,因为它们是正确的,而且...嗯,您无法克服。然而, 这是他们错过的 :
如果您要查看concat
的内部,您会发现该方法本身会检查Symbol.isConcatSpreadable
是对还是错。这可能会让您相信,如果spreadable
为 true (在Array
对象中默认为{em}),则它们的执行方式相同。根本不是真的。
虽然spread operator
在内部利用元素@@iterator
来组合数组/值,但Array.prototype.concat
方法的构建确实像for循环一样,即i=0;i<len;i++;
-实际上,在组合数组时,实际上是从被调用数组中弹出第一个元素,并执行断言和测试,而这些断言和测试在使用spread
时是不必要的。
好吧,这意味着如果您以某种方式调整迭代器并认为您正在使用spread
运算符连接Array,则上述两个示例的结果可能会大不相同。结果将不是达到您的期望。
在下面可以很容易地看出这一点:
let a = ["a","b","c"];
let b = ["d","e","f"];
b[Symbol.iterator] = function* () {
yield 1;
yield 2;
yield 3;
};
let c = JSON.stringify([].concat(a, b));
let d = JSON.stringify((a.push(...b), a));
console.log(c, d);
// a,b,c,d,e,f
// a,b,c,1,2,3
这也意味着不同于 Array.prototype.concat
方法,因为点差使用iterator
,并且可以手动提供/调整迭代器和迭代器可以异步-开拓了从未设计过concat
的潜在用途。
基本上,spread
是一个功能更全面的运算符,可用于许多不同的用例,而concat
实际上只是一个简单的“接受 this ”带有spreadable
的 there “,它只是确定是否应该对其较小的for循环执行值大于其for循环的mini for循环,或者内部数组引用是否足够好。
我希望这能回答您的问题,并让您进一步了解操作以及幕后的实际情况!
快乐编码!
答案 2 :(得分:4)
TL; DR
第一个是不纯的,第二个是纯的(尽管看起来是在已经不纯的上下文中完成的。)
说明
如果您使用.push
,则在其上调用Array
的{{1}}会发生变化,因为.push
在现有{{ 1}} 。
.push
代替创建新的Array
并将其他.concat
的附加到新的Array
。这样,原始Array
不会被更改。