Jeff Walden: New changes to make SpiderMonkey’s (and Firefox’s) parsing of destructuring patterns more spec-compliant |
One new feature in JavaScript, introduced in ECMAScript 6 (formally ECMAScript 2015, but it’ll always be ES6 in our hearts), is destructuring. Destructuring is syntactic sugar for assigning sub-values within a single value — nested properties, iteration results, &c., to arbitrary depths — to a set of locations (names, properties, &c.).
// Declarations var [a, b] = [1, 2]; // a = 1, b = 2 var { x: c, y: d } = { x: 42, y: 17 }; // c = 42, d = 17 function f([z]) { return z; } print(f([8675309])); // 8675309 // Assignments [b, f.prop] = [3, 15]; // b = 3, f.prop = 15 ({ p: d } = { p: 33 }); // d = 33 function Point(x, y) { this.x = x; this.y = y; } // Nesting's copacetic, too. // a = 2, b = 4, c = 8, d = 16 [{ x: a, y: b }, [c, d]] = [new Point(2, 4), [8, 16]];
One wrinkle to destructuring is its ambiguity: reading start to finish, is a “destructuring pattern” instead a literal? Until any succeeding =
is observed, it’s impossible to know. And for object destructuring patterns, could the “pattern” just be a block statement? (A block statement is a list of statements inside {}
, e.g. many loop bodies.)
ES6 says an apparent “pattern” could be any of these possibilities: the only way to know is to completely parse the expression/statement. There are more elegant and less elegant ways to do this, although in the end they amount to the same thing.
Object destructuring patterns present somewhat less ambiguity than array patterns. In expression context, {
may begin an object literal or an object destructuring pattern (just as [
does for arrays, mutatis mutandis). But in statement context, {
since the dawn of JavaScript only begins a block statement, never an object literal — and now, never an object destructuring pattern.
How then to write object destructuring pattern assignments not in expression context? For some time SpiderMonkey has allowed destructuring patterns to be parenthesized, incidentally eliminating this ambiguity. But ES6 chose another path. In ES6 destructuring patterns must not be parenthesized, at any level of nesting within the pattern. And in declarative destructuring patterns (but not in destructuring assignments), declaration names also must not be parenthesized.
As of several hours ago on mozilla-inbound, SpiderMonkey conforms to ES6’s parsing requirements for destructuring, with respect to parenthesization. These examples are all now syntax errors:
// Declarations var [(a)] = [1]; // BAD, a parenthesized var { x: (c) } = {}; // BAD, c parenthesized var { o: ({ p: p }) } = { o: { p: 2 } }; // BAD, nested pattern parenthesized function f([(z)]) { return z; } // BAD, z parenthesized // Top level ({ p: a }) = { p: 42 }; // BAD, pattern parenthesized ([a]) = [5]; // BAD, pattern parenthesized // Nested [({ p: a }), { x: c }] = [{}, {}]; // BAD, nested pattern parenthesized
Non-array/object patterns in destructuring assignments, outside of declarations, can still be parenthesized:
// Assignments [(b)] = [3]; // OK: parentheses allowed around non-pattern in a non-declaration assignment ({ p: (d) } = {}); // OK: ditto [(parseInt.prop)] = [3]; // OK: parseInt.prop not a pattern, assigns parseInt.prop = 3
These changes shouldn’t much disrupt anyone writing JS. Parentheses around array patterns are unnecessary and are easily removed. For object patterns, instead of parenthesizing the object pattern, parenthesize the whole assignment. No big deal!
// Assignments ([b]) = [3]; // BAD: parentheses around array pattern [b] = [3]; // GOOD ({ p: d }) = { p: 2 }; // BAD: parentheses around object pattern ({ p: d } = { p: 2 }); // GOOD
One step forward for SpiderMonkey standards compliance!
Комментировать | « Пред. запись — К дневнику — След. запись » | Страницы: [1] [Новые] |