Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
158 views
in Technique[技术] by (71.8m points)

Javascript unusual behavior regarding Array containing 1...N using spread operator

In Javascript, I make this simple ascending array by spread operator.

[...Array(5).keys()]
// printed list
[0, 1, 2, 3, 4]

But I simply added 1 and this unexpected array generated. (I just expected it would be an error)

[...Array(5).keys() + 1] 
// printed list
["[", "o", "b", "j", "e", "c", "t", " ", "A", "r", "r", "a", "y", " ", "I", "t", "e", "r", "a", "t", "o", "r", "]", "1"]

I would like to know what makes this behavior.

question from:https://stackoverflow.com/questions/65868308/javascript-unusual-behavior-regarding-array-containing-1-n-using-spread-operat

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

First, the expression to the right of the ... is evaluated. That is, Array(5).keys() + 1 gets evaluated, and the result of that evaluation is then spread. Grouping the expression may make things a little clearer:

[...(Array(5).keys() + 1)] 

So, above, we start with calculating the result of Array(5).keys() + 1. The + operator works between primitive operands. When you do Array(5).keys() you get an iterator back which is not classified as a primitive. So, JS will try and convert it to a primitive. When JS tries to convert the iterator into a primitive in this context it tries to:

  1. Invoke the iterator's Symbol.toPrimitive method, since this doesn't exist, it moves onto trying the next step
  2. Invoke the .valueOf() method of the iterator. This succeeds, but it returns the iterator back, which is not a primitive, so we go to the next step
  3. Invoke the .toString() method. This results in a non-object type (ie: a string), and so this is successful.

When the iterator's .toString() method is called it gets evaluated to "[object Array Iterator]". As this then gets added with the number 1, we concatenate the string with the number (rather than add), giving:

[..."[object Array Iterator]1"]

Since strings are iterable, the spread syntax will use the string's iterator to loop through the code points in the string, resulting in every character of the string becoming its own element:

["[", "o", "b", "j", "e", "c", "t", " ", "A", "r", "r", "a", "y", " ", "I", "t", "e", "r", "a", "t", "o", "r", "]", "1"]

In order to add one to each item in your iterator, you can use Array.from() which can take an iterator, and applies a mapping function to each element:

const res = Array.from(Array(5).keys(), i => i+1);
console.log(res);

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

1.4m articles

1.4m replys

5 comments

56.9k users

...