Clarify the destructuring syntax

# Егор Николаев (11 years ago)
  1. Should the AssignmentExpression of DestructuringAssignment always to be the Object type?
let {length} = "123";
assert(length, 3);

Is this valid?

If it is: 2. Should the result of Get(obj, name) always be the Object type if DestructuringAssignmentTarget is an ObjectLiteral or an ArrayLiteral? According the spec 12.14.5.4 step 4.b this expression is invalid:

let {text: {length}} = {text: "123"};
assert(length, 3);
# Till Schneidereit (11 years ago)

On Fri, Apr 11, 2014 at 12:35 PM, Егор Николаев <termi1uc1 at gmail.com> wrote:

  1. Should the AssignmentExpression of DestructuringAssignment always to be the Object type?
let {length} = "123";
assert(length, 3);

Is this valid?

Yes.

If it is: 2. Should the result of Get(obj, name) always be the Object type if DestructuringAssignmentTarget is an ObjectLiteral or an ArrayLiteral? According the spec 12.14.5.4 step 4.b this expression is invalid:

let {text: {length}} = {text: "123"};
assert(length, 3);

Yes.

You can test this in the web console in a Nightly or Aurora build of Firefox.

# André Bargull (11 years ago)

Hi Erop,

On Fri, Apr 11, 2014 at 12:35 PM, ???? ???????? <termi1uc1 at gmail.com, mail.mozilla.org/listinfo/es-discuss> wrote:

/ 1. Should the AssignmentExpression of DestructuringAssignment always to be />/ the Object type? />/ javascript />/ let {length} = "123"; />/ assert(length, 3); />/ />/ Is this valid? />/ / Yes.

No.

13.2.1.4 Runtime Semantics: Evaluation, LexicalBinding : BindingPattern Initializer, step 4

people.mozilla.org/~jorendorff/es6-draft.html#sec-let-and-const-declarations-runtime-semantics-evaluation

/ />/ If it is: />/ 2. Should the result of Get(obj, name) always be the Object type if />/ DestructuringAssignmentTarget is an ObjectLiteral or an ArrayLiteral? />/ According the spec 12.14.5.4 step 4.b this expression is invalid: />/ javascript />/ let {text: {length}} = {text: "123"}; />/ assert(length, 3); />/ />/ / Yes.

No.

13.2.3.7 Runtime Semantics: KeyedBindingInitialization BindingElement : BindingPattern Initializer_opt, step 4

people.mozilla.org/~jorendorff/es6-draft.html#sec-runtime-semantics-keyedbindinginitialization

You can test this in the web console in a Nightly or Aurora build of Firefox.

You can test this in traceur or my test implementation [anba/es6draft]. ;-)

Maybe the final draft will revert this restriction, it was originally introduced in rev17. It is somewhat annoying, especially for the string type, because the restriction also applies to spread array elements and spread calls. For example [..."abc"] must now be written as [...new String("abc")] to get the array of code points.

  • André
# Егор Николаев (11 years ago)

@Till Schneidereit. Sorry, but I am misunderstand you. Are you saying that this:

let {text: {length}} = {text: "123"};

is valid?

I am testing this behavior in traceur and FireFox. traceur says me that this is invalid spec says me that this is invalid FireFox 30.0a2 says to me that this is fine and quite logical.

# Till Schneidereit (11 years ago)

When in doubt, listen to André when it comes to spec details. So yes, it's valid in Firefox, but invalid per spec. Also, I agree that Firefox's behavior makes more sense, so I hope this'll change.

# Егор Николаев (11 years ago)

@André Bargull Are there any reasons for these restrictions? It confuses me. If I can for-of over string, so why can't I destructuring it?

# André Bargull (11 years ago)

On 4/11/2014 2:02 PM, Егор Николаев wrote:

@André Bargull Are there any reasons for these restrictions? It confuses me. If I can for-of over string, so why can't I destructuring it?

I'd say it's mostly a language designer decision and it may still change before the final specification is published. I'd encourage you to file bug reports at bugs.ecmascript.org and/or post to this mailing list if you find any issues with the current specification draft. That way Allen (the spec editor, cc-ed) and other TC-39 members are notified and can take appropriate actions.

  • André
# Allen Wirfs-Brock (11 years ago)

On Apr 11, 2014, at 5:22 AM, André Bargull wrote:

On 4/11/2014 2:02 PM, Егор Николаев wrote:

@André Bargull Are there any reasons for these restrictions? It confuses me. If I can for-of over string, so why can't I destructuring it?

I'd say it's mostly a language designer decision and it may still change before the final specification is published. I'd encourage you to file bug reports at bugs.ecmascript.org and/or post to this mailing list if you find any issues with the current specification draft. That way Allen (the spec editor, cc-ed) and other TC-39 members are notified and can take appropriate actions.

This was discusses fairly extensively in TC39 meetings and on this list. The final consensus was that non objects should not be destructurable (ie, ToObject is not applied). One argument against allowing non-objects is that it might be future-hostile to anticipated future proposal to turn destructuring into more general pattern patching,

This is the decision that is reflected in the ES6 draft starting with rev17. As it stand right now, there is no advocacy within TC39 for reopening this decision.

# Егор Николаев (11 years ago)

On the one hand, the is a bug in current spec that allows the

let {length} = "qwe";

but disallow

let {text: {length}} = {text: "qwe"};

On the other hand, this restriction can lead to hard-reproducibly errors. When I write a function such as:

function returnLength( {length} ) {
    return length;
}

I can't be sure that foreign user will not use it as:

var obj = { toString(){ return "test" } };
returnLength( obj + "" );

In this case, I have no other chose, but to rewrite function without destructuring in function parameter:

function returnLength( text ) {
    text = new String(text);// do not remove it, without this line following
destructuring pattern will throw a error
    let {length} = text;
    return length;
}

Of course, in real app this function would be more complex.

# Allen Wirfs-Brock (11 years ago)

On Apr 11, 2014, at 8:56 AM, Егор Николаев wrote:

On the one hand, the is a bug in current spec that allows the

let {length} = "qwe";

Where in the spec. the bug? Is a ticket filed for it? Indeed, this is supposed to be an error.

# Егор Николаев (11 years ago)

The ticket ecmascript#2639

# Егор Николаев (11 years ago)

After firing a bug I read the spec again and realised that Get (O, P) should already throw a Error. So maybe I am misunderstood this from the beginning. In this case section "12.14.5.4 4.b. If Type(v) is not Object, then throw a TypeError exception." is useless because it already has a type checking in Get function.

# Allen Wirfs-Brock (11 years ago)

On Apr 11, 2014, at 10:29 AM, Егор Николаев wrote:

After firing a bug I read the spec again and realised that Get (O, P) should already throw a Error. So maybe I am misunderstood this from the beginning. In this case section "12.14.5.4 4.b. If Type(v) is not Object, then throw a TypeError exception." is useless because it already has a type checking in Get function.

The top level assignment check is done in 12.14.4 step 6