Define static properties and prototype properties with the class syntax

Glen Huang curvedmark at gmail.com
Sat Dec 13 11:09:55 PST 2014


Hey Rick,

Thank you for the explanation and sample code. I made a mistake there. I was demonstrating that the syntax already allows an object to exist in the prototype chain, so the static keyword really shouldn’t be there.

And you know, I’m still struggling with the idea of an object being in the prototype chain is a bad one or not. I think for people who know what they are doing, it definitely helps. But if the language wants to prevent footgun features for everybody, it seems that it does make sense to make it more limited. So I’m torn right know.

I know you are in the TC39 team (Frankie and Kevin might also be on the team, I’m not sure, would be interested to know if there is a TC39 team member list), and I’d be grateful if you could share your thoughts on this.

Thank you.

> On Dec 14, 2014, at 2:44 AM, Rick Waldron <waldron.rick at gmail.com> wrote:
> 
> 
> 
> On Sat Dec 13 2014 at 4:54:55 AM Glen Huang <curvedmark at gmail.com <mailto:curvedmark at gmail.com>> wrote:
> But allowing getter & setter already makes it dangerous:
> 
> let _bar = {}
> class Foo {
>         static get bar() { return _bar; }
> }
> 
> Objects that have Foo.prototype in the prototype chain can do "this.bar.a = 1", and the change won’t be shadowed.
> 
> The accessor property "bar" is _not_ created on Foo.prototype, it's created on Foo itself and would not be found on `this`.
> 
> In ES5, the example above would look like this: 
> 
> var _bar = {};
> var Foo = function Foo() {}
> 
> Object.defineProperty(Foo, "bar", {
>   get: function() {
>     return _bar;
>   }
> });
> 
>  
> 
> I found myself looking for a way to define static properties because I want to do this:
> 
> function Menu(options) {
>         this.options = Object.assign({}, Menu.defaults, options);
> }
> Menu.defaults = { hidden: false };
> 
> 
>   class Menu {
>     constructor(options) {
>        this.options = Object.assign({}, Menu.defaults, options);
>     }
>     static get defaults() {
>       return Object.freeze({ hidden: false });
>     }
>   }
> 
> This has the benefit of preventing unwanted tampering with `Menu. defaults` by ensuring that the only way to modify defaults is by explicitly providing them via  `new Menu({ my opts })`. The property can be _read_ as `Menu.defaults` but assignment to `Menu.defaults` or attempts to change values or add properties will throw. 
> 
> 
>  
> I want to expose the defaults property so it can be modified by users. This pattern is very ubiquitous in es5. I wonder if the class syntax could allow this pattern to be carried to es6?
> 
> ES6 is done, but this is something that I also want to revisit for ES7 (should be a year following ES6). In the meantime, it's not too painful to address this use case by doing this: 
> 
>   class Menu {
>     constructor(options) {
>        this.options = Object.assign({}, Menu.defaults, options);
>     }
>   }
> 
>   Menu.defaults = { hidden: true };
> 
> Though I'm not sure what the benefit is to allowing any code access to an the unprotected defaults. If you and I are working on a large system using this class, with potentially many Menu components on the same page and I change the defaults, all other code can no longer trust the defaults to be correct. That said, it's not always as simple as creating a closure with the defaults so they're not exposed at all—exposing them is certainly useful for testing, and/or verifying correct, expected initial state with some baseline shape. 
> 
> Rick

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20141214/43c42e6b/attachment-0001.html>


More information about the es-discuss mailing list