Syntax Proposal: Allow Java-like Object Literals after constructor calls to set properties on created objects.

Erik Arvidsson erik.arvidsson at gmail.com
Thu Jul 1 12:16:48 PDT 2010


A lot of discussion since I last checked in...

I apologize for the harshness. I do agree that Object.create is useful
and I agree that the default values for the property descriptor is
acceptable even though having read only be the default is painful but
consistency trumps that one.

My main issue is actually that Object.create is such a low level
construct. It is very good for library authors to hide it behind a
friendlier interface. I wish Object.create was called something more
obscure and Object.create was targeting end users. Instead of passing
a map of property descriptors an object would be passed. I just find
the extra layer of object literals too much.

var o = Object.create(Foo.prototype, {
  _a: {
    value: 1,
    writable: true,
  },
  a: {
    get: function() { return this._a; },
    set: function(a) { this._a = a; },
    enumerable: true
  }
};

If Object.create was created with users in mind it might have looked
something like:

var o = Object.create(Foo.prototype, {
  _a: 1,
  get a() { return this._a; },
  set a(a) { this._a = a; }
});

Looking forward, I like where Allen is going with the extended object
literals. Today, we can do the following in most browsers (relying on
the __proto__ extension).

var o = {
  __proto__: Foo.prototype,
  _a: 1,
  get a() { return this._a; },
  set a(a) { this._a = a; }
};

This is clearly a usability win, even with the ugly underscores. With
Allens proposal that would become:

var o = {
  [proto: Foo.prototype]
  _a: 1,
  get a() { return this._a; },
  set a(a) { this._a = a; }
};


On Thu, Jul 1, 2010 at 11:40, Mark Miller <erights at gmail.com> wrote:
>
>
> On Thu, Jul 1, 2010 at 11:13 AM, Mark S. Miller <erights at google.com> wrote:
>>
>> On Thu, Jul 1, 2010 at 8:24 AM, Brendan Eich <brendan at mozilla.com> wrote:
>>>
>>> On Jul 1, 2010, at 2:13 AM, Mark S. Miller wrote:
>>>
>>> On Wed, Jun 30, 2010 at 9:09 PM, Brendan Eich <brendan at mozilla.com>
>>> wrote:
>>>>
>>>> On Jun 30, 2010, at 7:37 PM, Mark S. Miller wrote:
>>>>>
>>>>> And you're right that attribute-property-missing -> undefined -> false
>>>>> has an effect here. If we had kept the ES3 negative names, we could have
>>>>> defaulted to false and Erik (I think) would not find Object.create a mistake
>>>>> -- but then the high-integrity-by-default fans would be put out. Those fans
>>>>> should speak up if they care to defend against the "mistake" charge.
>>>>
>>>> Fine. Had it defaulted to low integrity, that would have been a mistake.
>>>> Erik & I know we disagree on this.
>>>>
>>>> Allen seems to agree with Erik. Is this just a matter of personal
>>>> opinion?
>>>
>>> More that just personal opinion. At this point I think there is good
>>> evidence that Allen agrees with Erik ;).
>>>
>>> LOL, pronoun trouble. I meant by "this" the whole "X is a mistake... !X
>>> is a mistake" approach, which seemed in your mail to come down to
>>> he-said/I-said ;-).
>>>
>>>
>>>>
>>>> The point that I don't see you responding to is that the Object.create
>>>> defaults are opposite from what every other way of binding a property in the
>>>> language uses.
>>>
>>> Every other is two: 1) assignment, or 2) object literals.
>>>
>>> 3) Declaration by var/function -- makes non-configurable unless from
>>> eval, but *writable*.
>>
>> As we're moving away from object environment records, I take the world of
>> variables and the world of properties to be distinct.
>> For variables in Harmony, we're introducing "const" and "let" and
>> effectively deprecating "var". For a variable that's never assigned to, I
>> suggest that "const" is better style. Then those variables declared with
>> "let" stand out, signaling to the programmer "Assume this variable may be
>> assigned to".
>> Named function expressions already bind the function name with a const
>> (unassignable) binding. Regarding named function declarations, I find
>> <http://wiki.ecmascript.org/doku.php?id=strawman:const_functions>
>> attractive. IIRC, so do you. I've just added a "High Integrity Factories"
>> example to the end of that page. That example does demonstrate my one regret
>> about the definition of Object.create() -- that it defaults to creating an
>> extensible object, requiring a separate Object.freeze() to complete the
>> second example. Because of this "mistake", the complete second example is no
>> longer pleasantly terse.
>>
>>>
>>> 4) Pre-defined bindings are mostly writable -- built-in constructors'
>>> 'prototype' properties are a notable exception.
>>> Writability rather than configurability or enumerability is the bone of
>>> contention, I think. Of course all three default the high-integrity way in
>>> Object.create, and I wouldn't want to split them up, some defaulting to true
>>> while others to false.
>>
>> Glad to hear it. Our positions are closer than I'd feared. My main concern
>> in the design was ensuring that configurability defaulted to false. Besides
>> integrity, this should also enable various optimizations. When combined with
>> non-extensibility, it gives us objects of fixed state.
>
> I meant "fixed shape". An especially confusing typo in this context, sorry.
>
>
>>
>> That said, I still think writable defaulting false was the right decision.
>>
>>>
>>> What  I'm suggesting is that writable:false is what sticks out as less
>>> usable, especially for cases such as the Rhino object initializer extension
>>> recast using Object.create as in Allen's mail.
>>
>> OTOH, the Classes as Sugar to-be-strawman at
>> <https://mail.mozilla.org/pipermail/es-discuss/2009-March/009115.html>
>> expands to defining frozen instances. To get the scoping benefit that Peter
>> Michaux suggested -- where public instance members are also in scope as
>> variables in the defining context -- to work for mutable variables/instance
>> fields, the only non-with-way to do that is to have the instance fields be
>> defined as accessors accessing the variable. This is consistent with the
>> instance being frozen.
>>
>>>
>>> These already make low integrity easy. Prior to ES5, high integrity was
>>> impossible. A new API introduced to support high integrity should also make
>>> it easy -- if it's not easy to be safe, few will. Low integrity remains easy
>>> through assignment and object literals.
>>>
>>> Yes, this was the rationale and I went along with it -- still do. I'm not
>>> jumping up and down about "mistake" here, rather trying to draw out exactly
>>> what is at issue. Calling Object.create "a mistake" in full is excessive,
>>> since it has other useful features that are not considered broken AFAIK.
>>> The way to make progress (for future extensions, nothing's going to
>>> change in ES5) is to tease out the compositional, reduced or "primitive"
>>> missing semantics we may want to add to the language, and not condemn
>>> composite extensions wholesale. We can then argue about usability and
>>> convenience more clearly.
>>> So my disagreement in the end (as in my initial followup!) is with Erik
>>> for condemning all of Object.create. There's good stuff in there, even if
>>> the defaults are less usable for some (more familiar, like what you can do
>>> in JS today) use-cases.
>>>
>>> The agreed Harmony goal of "Provide syntactic support for high integrity
>>> patterns",
>>>
>>> Don't see those words
>>> at http://wiki.ecmascript.org/doku.php?id=harmony:harmony -- but I won't
>>> quibble :-|.
>>
>> See <http://wiki.ecmascript.org/doku.php?id=harmony:harmony#means> 2.II.
>> s/support/conveniences/
>>
>>>
>>> as well as the repeatedly stated desires for some kind of class construct
>>> going back to ES4, shows that we did not go far enough in making high
>>> integrity easy. But we did what we could within the ES5 constraints. I'm
>>> glad we didn't do less. The easy way should be the safe way.
>>>
>>> As Allen said, the defaults being different make Object.create less
>>> usable for approximating extensions such as the Rhino
>>> your-constructor-call-with-args+object-initialiser-for-extra-properties one.
>>> That's clear enough without assuming anything beyond what was in Rhino's
>>> extension, or in ES1-3 or JS as practiced today -- i.e., without assuming
>>> that the user wants higher integrity, specifically non-writable properties.
>>> Object.create has great defaults for creating built-in-like properties,
>>> akin to built-in constructor 'prototype', and of course for creating even
>>> more heavily armored objects. No question! ;-)
>>> So, in the category "bleeding obvious" (I hope), and without beating the
>>> issues in this thread to death no further, my conclusion is that the Rhino
>>> extension or something that fills its usability gap it wants new syntax and
>>> not Object.create. I do not mean to imply either that we should add the
>>> Rhino extension (mutatis mutandis), or that Object.create is "a mistake".
>>> Hope this helps,
>>
>> It helps a lot. Thanks. Our positions are indeed fairly close.
>>
>>>
>>> /be
>>
>>
>> --
>>     Cheers,
>>     --MarkM
>>
>> _______________________________________________
>> es-discuss mailing list
>> es-discuss at mozilla.org
>> https://mail.mozilla.org/listinfo/es-discuss
>>
>
>
>
> --
> Text by me above is hereby placed in the public domain
>
>    Cheers,
>    --MarkM
>
>



-- 
erik


More information about the es-discuss mailing list