此javascript作业有什么区别?

时间:2019-04-11 16:24:39

标签: javascript arrays

这两个作业之间有什么区别?

this.list.push(...response.data);

//vs

this.list = [].concat(this.list, response.data);

3 个答案:

答案 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不会被更改。