简体   繁体   English

数组解构和散布运算符

[英]Array destructuring and spread operator

It's not 100% clear to me how this piece of code works: 我不太清楚这段代码是如何工作的:

var a = [1, 2, 3];

[x, y, ...a ] = [0, ...a, 4];

// OUTPUT:  [0, 1, 2, 3, 4]

I'm deconstructing the array a using the ... operator. 我正在使用...运算符来解构数组a

I am expecting that in second line a bunch of assignments will take place. 我期望在第二行中会进行许多作业。

The x will be assigned to 0, y will be assigned to ...a (which passes the elements in the array a as individual values). x将被分配为0, y将被分配给...a (它将数组a的元素作为单独的值传递)。

It's not clear to me, though, how the ...a get assigned to 4. In fact, JS throws an exception when doing: 但是,我不清楚如何将...a分配给4。实际上,JS在执行以下操作时会引发异常:

...a = 4;
// Uncaught SyntaxError: Rest parameter may not have a default initializer

Why does this code output the modified array with the end 4 , instead of throwing an exception? 为什么这段代码为什么输出修改后的数组以4结尾,而不是抛出异常? How does this work exactly? 究竟如何运作?

It is executed like following 如下执行

var a = [1, 2, 3];
[x, y, ...a ] = [0, ...a, 4];
[x, y, ...a ] = [0, 1, 2, 3, 4];

which means first value in RHS array is assigned to x , second value in RHS array is assigned to y and the remaining values are assigned to a . 这意味着RHS数组中的第一个值分配给x ,RHS数组中的第二个值分配给y ,其余值分配给a

Hence, value of x is 0 , y is 1 and a is [2, 3, 4] 因此, x值为0y1a[2, 3, 4]

...a is either equal to .slice(start, end) (left, destructuring) or to .concat(a) (right, spreading): ...a等于.slice(start, end) (左,解构)或.concat(a) (右,扩展):

 [0, ...a, 4]

is equal to: 等于:

[0].concat(a).concat([4]) // [0,1,2,3,4]

Whereas: 鉴于:

[x, y, ...a] = array

Is equal to: 等于:

x = array[0];
y = array[1];
a = array.slice(2);

It's not clear to me, though, how the ...a get assigned to 4 . 不过,我不清楚...a如何将...a分配给4

It's not. 不是。

Lets split things up a little: 让我们把东西分开:

On the right hand side of the assignment you are using an array literal with a spread element . 在赋值的右侧,您使用带有扩展元素的数组文字。 The value of a is "flattened" into the new array. 的值a被“展平”到新的数组。

Thus, [0, ...a, 4] is is equivalent to [0].concat(a, [4]) . 因此, [0, ...a, 4]等效于[0].concat(a, [4]) The result is a new array. 结果是一个新的数组。

 var a = [1, 2, 3]; console.log('spread element', [0, ...a, 4]); console.log('concat', [0].concat(a, [4])); 

On the left hand side you are using array destructuring with a rest element . 在左侧,您正在使用带有rest元素的数组解构。 [x, y, ...a ] means [x, y, ...a ]表示

  • assign the first value of the iterable to x 将iterable的第一个值分配给x
  • assign the second value of the iterable to y 将可迭代的第二个值分配给y
  • assign the remaining values of the iterable as an array to a 将剩余的iterable值作为数组分配a

These two are equivalent: 这两个等效:

 var a = [1,2,3,4]; var [x, y, ...z] = a; console.log('destructuring', x, y, z); var x = a[0]; var y = a[1]; var z = a.slice(2); console.log('manual + slice', x, y, z); 


Of course combining these two is perfectly fine. 当然,将两者结合起来是完全可以的。 In an assignment, the left hand side doesn't care what how the right hand side is computed and vice versa. 在作业中,左侧不关心右侧的计算方式,反之亦然。

What's confusing about your example is that you are using a again in the destructuring assignment, but that's the same as overriding the value of a with a new value. 什么是混淆你的例子是,你正在使用a在解构赋值再次,但这是一样压倒一切的价值a新值。 However the end result is 但是最终结果是

  • [0, ...a, 4] results in [0,1,2,3,4] therefor [0, ...a, 4]结果是[0,1,2,3,4]
  • x has value 0 x值为0
  • y has value 1 y值为1
  • a has value [2,3,4] a值为[2,3,4]

In fact, JS throws an exception when doing: ...a = 4; 实际上,JS在执行以下操作时会引发异常: ...a = 4;

The error message you are getting is strange. 您收到的错误消息很奇怪。 It should really be just a syntax error. 它实际上应该只是语法错误。

... by itself doesn't mean anything. ...本身并不意味着任何事情。 It's not an operator, it's a punctuator (like ; or , ) that has a different meaning depending on the context it is used (and allowed). 它不是运算符,它是一个标点符号(如;, ),根据使用(允许)的上下文而具有不同的含义。

See also What is SpreadElement in ECMAScript documentation? 另请参阅ECMAScript文档中的SpreadElement是什么? Is it the same as Spread operator at MDN? 它与MDN的Spread运算符相同吗?

In the first example, spread ie ... in LHS acts as gatherer whereas on the RHS it acts as spread/rest. 在第一个示例中,LHS中的传播即...充当收集者,而在RHS中它充当传播/休息。 IE you are assigning value to variable a when it is on LHS. 在IE中,当您在LHS上为变量a分配值时。

 var a = [1, 2, 3]; [x, y, ...a ] = [0, ...a, 4]; console.log(a) 

Let's go step by step: 让我们一步一步走:

Let's start with RHS. 让我们从RHS开始。 Doing [0, ...a, 4] will generate [0, 1, 2, 3, 4] . 进行[0, ...a, 4]将生成[0, 1, 2, 3, 4] See for yourself: 你自己看:

 var a = [1, 2, 3]; console.log([0, ...a, 4]); 

Now, the LHS is the side where assignment is taking place. 现在, LHS是进行分配的一方。 On RHS, imagine any variable with spread operator as an array ready to be assigned new values. 在RHS上,想象一下任何具有扩展运算符的变量都可以作为一个array准备为其分配新值。

So, we are trying to assign [0, 1, 2, 3, 4] to a variable x , then to y and the rest to array a ( in that order ). 因此,我们尝试将[0, 1, 2, 3, 4]分配给变量x ,然后分配给y ,其余分配给数组a按此顺序 )。 So, array a will have whatever will be left after first two assignments (ie 2, 3, 4 ). 因此,数组a在前两个赋值(即2, 3, 4 )之后将剩下什么。

 var a = [1, 2, 3]; // a will get overwritten [x, y, ...a ] = [0, 1, 2, 3, 4]; // same as [x, y, ...a ] = [0, ...a, 4]; console.log(a); 

Finally, coming to your last question: "It's not clear to me, though, how the ...a get assigned to 4? " 最后,最后一个问题是:“不过,我不清楚,...如何分配给4?”

Answer: It is not . 答: 不是 But if you do something like [...a] = [4] , it will result in an array named a containing [4] . 但是,如果您执行[...a] = [4] ,则将导致名为a的数组包含[4]

You can read more about spread syntax here (MDN) and here (YDKJS) . 您可以在此处(MDN)此处(YDKJS)阅读有关扩展语法的更多信息。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM