Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Destructuring assignment in generator expressions and array comprehensions

Tags:

javascript

Why does for ([] in object); work fine but [void 0 for ([] in object)] or (void 0 for ([] in object)) throw a syntax error for invalid left-hand assignment?

For example, I would expect the following code to work, but it doesn't (the assertion isn't even done due to the syntax error):

let (
  i = 0,
  iterable = {__iterator__:function() { var i = 5; while (i--) yield i; } }
) {
  for ([] in iterable) i++;
  console.assertEquals([void 0 for ([] in iterable)].length, i);
}
like image 987
Eli Grey Avatar asked Mar 25 '10 23:03

Eli Grey


People also ask

What is Destructuring assignment?

The destructuring assignment syntax is a JavaScript expression that makes it possible to unpack values from arrays, or properties from objects, into distinct variables.

What is Destructuring in array?

Destructuring in JavaScript is a simplified method of extracting multiple properties from an array by taking the structure and deconstructing it down into its own constituent parts through assignments by using a syntax that looks similar to array literals.

Can you give an example of Destructuring an object or an array?

In the first line, we are declaring a new variable studentsArr , and assigning it the value of an array of student names. Line 2 is where we destructure. In line 2 we declare three variables; first , second , and third . By declaring them on the left-hand side, we initiate destructuring.

What is Destructure?

To destroy the structure of something. To dismantle.


1 Answers

I did a little digging in jsparse.c of SpiderMonkey (which I assume is the JS parser you're using for 1.8 features?)

The [code for (... in ...)] format or generator expression uses a different parse function than the standard for ([] in obj) uses.

Your LHS error is being created here: (jsparse.c line 4200)

4194           case TOK_LB:
4195           case TOK_LC:
4196             pn3 = DestructuringExpr(cx, &data, tc, tt);
4197             if (!pn3)
4198                 return NULL;
4199 
4200             if (pn3->pn_type != TOK_RB || pn3->pn_count != 2) {
4201                 js_ReportCompileErrorNumber(cx, ts, NULL, JSREPORT_ERROR,
4202                                             JSMSG_BAD_FOR_LEFTSIDE);
4203                 return NULL;
4204             }

When it sees the [ it finds the Destructuring Expression, and ensures the count of the parser node is at 2.

Interestingly enough [void 0 for ([a,b] in iterator)] should work, although for reasons I don't care to go digging for, the b from [a,b] is always undefined:

js> [[l1,typeof l2] for ([l1,l2] in {a:1, b:2})]
a,undefined,b,undefined

For reference - The standard for([] in {}) uses the following logic to determine the LHS validity:

2775 #if JS_HAS_DESTRUCTURING
2776                    ((JSVERSION_NUMBER(cx) == JSVERSION_1_7 &&
2777                      pn->pn_op == JSOP_FORIN)
2778                     ? (pn1->pn_type != TOK_RB || pn1->pn_count != 2)
2779                     : (pn1->pn_type != TOK_RB && pn1->pn_type != TOK_RC)) &&
2780 #endif

Which seems to mean that versions other than 1.7 don't require 2 left hand values for this syntax. The generator expression might be using older parsing logic. This might be worth submitting as a report to the SpiderMonkey maintainers.

like image 198
gnarf Avatar answered Sep 22 '22 14:09

gnarf