Loyal Opposition to Const, Private, Freeze, Non-Configurable, Non-Writable...

# Jeremy Ashkenas (14 years ago)

On Wed, Nov 2, 2011 at 11:01 AM, David Bruant <bruant.d at gmail.com> wrote:

Could you elaborate on this point? All object-lockdown I can think (non-configurability, non-writability, non-enumerability, private names, const variables, const classes) of is optional. Why are you against them?

I was about to say "if you're unsatisfied, create a language which doesn't provide features you don't like, like Coffeescript", but... humm... So, why being against the introduction of features in the language?

I'd be glad to elaborate -- but since it's off topic for minimal classes, changing the Subject here.

What draws people to dynamic languages is freedom.

And JavaScript is one of the most dynamic of the mainstream programming languages. Not only can you can pass any object to any function, but you can call a method with any number of arguments, easily modify the prototypes of other objects, introspect on any object's properties with a simple loop, replace any member function with a wrapped version, attach new properties to any object ... the list goes on.

If I had my druthers, JS.next would generally embrace the spirit of JavaScript's dynamism (and freedom), and try to push those aspects further -- with better introspection and more flexibility -- instead of compromising with more restrictive static languages and adding lock-down keywords so that some programmers might "feel safer".

Let's set arguments about security and constraint guarantees aside for a moment (although I'd be glad to have those as well), and talk about these keywords as pure features:

"private" does not add anything new to a property. If you don't want the property to be used outside of the class ... don't use the property outside of the class.

"const" does not add anything new to a variable. If you don't want to change the value of a variable ... don't change the value of the variable.

"freeze" does not add anything new to an object. If you don't want to change the shape of an object ... don't change the shape of the object.

Note that Ruby, another very dynamic language, has "private" and constants. And yet private methods can be called from the outside, with "send", and contants can be explicitly overwritten with new values. They are simply red tape, not concrete walls. For better or for worse, I have very rarely seen a large-scale Ruby project that does not call a private method externally, or overwrite a constant during configuration.

The recent JavaScript renaissance that we're all enjoying owes debts to JavaScript's foresight as a "free", dynamic language. If all of the JavaScript core object had been frozen, locked down with private methods, and set as const properties on the global object, libraries like Prototype.js never would have happened. Libraries like jQuery would have been much more difficult to imagine. We might not have the new Array#map, #reduce, #every, or #filter methods at all.

Can a free, dynamic language be abused? Certainly. Is Prototype.js dangerous? For some websites, it can be (including NYTimes.com, where I work).

The freedom of having every object and every property be configurable, settable, introspectable, readable and writable, at least at the language level, is worth the trade off. If we add const, private, and other lock-down syntax, or make class properties private by default (shudder), I guarantee you that many potential innovative libraries that otherwise might spring up will never even be conceived, and frustrating situations that could have otherwise been solved by a quick patch will instead require convoluted work-arounds.

JavaScript should be about making it easier to write the right thing, and not so much about making it harder to do the wrong thing. After all, the former is purely positive, and the latter assumes that you know better than the engineer who comes after you. In the real world, you often don't.

# John J Barton (14 years ago)

On Wed, Nov 2, 2011 at 9:05 AM, Jeremy Ashkenas <jashkenas at gmail.com> wrote:

On Wed, Nov 2, 2011 at 11:01 AM, David Bruant <bruant.d at gmail.com> wrote:

Could you elaborate on this point? All object-lockdown I can think (non-configurability, non-writability, non-enumerability, private names, const variables, const classes) of is optional. Why are you against them? ... The freedom of having every object and every property be configurable, settable, introspectable, readable and writable, at least at the language level, is worth the trade off. If we add const, private, and other lock-down syntax, or make class properties private by default (shudder), I guarantee you that many potential innovative libraries that otherwise might spring up will never even be conceived, and frustrating situations that could have otherwise been solved by a quick patch will instead require convoluted work-arounds.

Another maybe stronger argument is simplicity: these myriad new minor features create a blizzard of chaff in the way of developers. One excellent example is Object.create(). Here was a terrific opportunity to simplify the language based on years of experience and analysis. But instead of an object as a second argument, we got a descriptor requiring many details for each property. Of course these details are important for the use-cases that need them. Unfortunately everyone else has to carry the baggage.

jjb

# Quildreen Motta (14 years ago)

On 02/11/11 14:05, Jeremy Ashkenas wrote:

On Wed, Nov 2, 2011 at 11:01 AM, David Bruant <bruant.d at gmail.com <mailto:bruant.d at gmail.com>> wrote:

Could you elaborate on this point?
All object-lockdown I can think (non-configurability,
non-writability, non-enumerability, private names, const
variables, const classes) of is optional. Why are you against them?

I was about to say "if you're unsatisfied, create a language which
doesn't provide features you don't like, like Coffeescript",
but... humm...
So, why being against the introduction of features in the language?

I'd be glad to elaborate -- but since it's off topic for minimal classes, changing the Subject here.

What draws people to dynamic languages is freedom.

I'd put extensibility' andexpressivity' here instead, but sure. And JavaScript does pretty good at that --- not as much as Lisp, but oh well, it's not like I expected a C-family language to be that extensible :3

If I had my druthers, JS.next would generally embrace the spirit of JavaScript's dynamism (and freedom), and try to push those aspects further -- with better introspection and more flexibility -- instead of compromising with more restrictive static languages and adding lock-down keywords so that some programmers might "feel safer".

Agreed. But there are other things here other than "security constraints".

"private" does not add anything new to a property. If you don't want the property to be used outside of the class ... don't use the property outside of the class.

I still haven't found an use to private either, to be honest. Granted I often declare "private" functions and variables inside a closure, I always export them in an `internal' object, so it doesn't clutter the core API.

"const" does not add anything new to a variable. If you don't want to change the value of a variable ... don't change the value of the variable.

I'm not sure I agree here. Constants are not about security they're about abstractions. You name something that you'd otherwise have to write as a regular expression. In this case, they'd be like a really simple inline function, except they do no transformations.

"freeze" does not add anything new to an object. If you don't want to change the shape of an object ... don't change the shape of the object.

Again, immutability isn't just about security, but optimisation as well. You could also look at shared-memory threads, because I think they make a hell of an argument for "frozen" objects or immutability.

JavaScript should be about making it easier to write the right thing, and not so much about making it harder to do the wrong thing. After all, the former is purely positive, and the latter assumes that you know better than the engineer who comes after you. In the real world, you often don't.

Agreed, but note that none of the features above preclude JavaScript from being a free language that makes it easier to write the right thing. It'll be just as expressive as before. Also note that you can already achieve all of those functionality in current JavaScript, so having class-literals, as a declarative syntax, support them in a nice way is okay.

It's not like any feature can't be abused as you say. But the fact that a feature can be abused doesn't mean it should be never considered. JavaScript's `with' is a good example of that. You could create the most awesome and expressive module library using that, but no vendors have optimized it (as far as I know) because people considered it could only ever be abused and haven't used it.

Also, note that with' makes a whole awesome use-case forObject.freeze':


with (require({'library1': 'lib1'}, {'library2': 'lib2'})) { lib1.foo(lib2.something) } // Would be equivalent to Python's // import library1 as lib1 // import library2 as lib2 // // But restricted to a block.

You could also use it as a dynamic let, and just as long as you freeze the object passed to with', there's no reason one shouldn't optimize it as just a regular EnvironmentRecord lookup. Usinglet' instead of var' removes the thing about variable hoisting declaring the variable outside of thewith' scope, etc.

tl;dr; While private',const' and freeze' could certainly be abused, that doesn't mean they don't have value... well, perhaps except forprivate'.

# Quildreen Motta (14 years ago)

On 02/11/11 14:26, John J Barton wrote:

Another maybe stronger argument is simplicity: these myriad new minor features create a blizzard of chaff in the way of developers. One excellent example is Object.create(). Here was a terrific opportunity to simplify the language based on years of experience and analysis. But instead of an object as a second argument, we got a descriptor requiring many details for each property. Of course these details are important for the use-cases that need them. Unfortunately everyone else has to carry the baggage. Object.create' is not supposed to be used directly by end-users. It's for library writers. Library writers get the heavy weight and generic things, and transform that for a specific use-case. Of course, not having anObject.extend' and other object composition functionality makes things a little too meh.

# David Bruant (14 years ago)

Le 02/11/2011 17:26, John J Barton a écrit :

On Wed, Nov 2, 2011 at 9:05 AM, Jeremy Ashkenas <jashkenas at gmail.com> wrote:

On Wed, Nov 2, 2011 at 11:01 AM, David Bruant <bruant.d at gmail.com> wrote:

Could you elaborate on this point? All object-lockdown I can think (non-configurability, non-writability, non-enumerability, private names, const variables, const classes) of is optional. Why are you against them? ... The freedom of having every object and every property be configurable, settable, introspectable, readable and writable, at least at the language level, is worth the trade off. If we add const, private, and other lock-down syntax, or make class properties private by default (shudder), I guarantee you that many potential innovative libraries that otherwise might spring up will never even be conceived, and frustrating situations that could have otherwise been solved by a quick patch will instead require convoluted work-arounds. Another maybe stronger argument is simplicity: these myriad new minor features create a blizzard of chaff in the way of developers. One excellent example is Object.create(). Here was a terrific opportunity to simplify the language based on years of experience and analysis. But instead of an object as a second argument, we got a descriptor requiring many details for each property. Of course these details are important for the use-cases that need them. Unfortunately everyone else has to carry the baggage.

I agree that the second argument is a design mistake. But ES6 will fix this with the proto operator.

# Mikeal Rogers (14 years ago)

I agree with every sentence in this post.

+1K :)

# Peter van der Zee (14 years ago)

On Wed, Nov 2, 2011 at 5:44 PM, David Bruant <bruant.d at gmail.com> wrote:

I agree that the second argument is a design mistake. But ES6 will fix this with the proto operator.

"fix"

It has the same kind of baggage and goes into the "minor features" category, at least in terms of syntax, in my opinion.

# Mikeal Rogers (14 years ago)

On Nov 2, 2011, at November 2, 20119:30 AM, Quildreen Motta wrote:

"freeze" does not add anything new to an object. If you don't want to change the shape of an object ... don't change the shape of the object. Again, immutability isn't just about security, but optimisation as well. You could also look at shared-memory threads, because I think they make a hell of an argument for "frozen" objects or immutability.

The last time we looked at freezing a few core objects in node.js we found that v8 was actually slower with them frozen and backed them out, which is probably a good thing.

I'm very skeptical of the "new language feature for optimization" argument ever since the static typing debate in ES4 and the tracer work Mozilla did shortly after.

# Brendan Eich (14 years ago)

On Nov 2, 2011, at 9:05 AM, Jeremy Ashkenas wrote:

I'd be glad to elaborate -- but since it's off topic for minimal classes, changing the Subject here.

Thanks for that.

What draws people to dynamic languages is freedom.

And JavaScript is one of the most dynamic of the mainstream programming languages. Not only can you can pass any object to any function, but you can call a method with any number of arguments, easily modify the prototypes of other objects, introspect on any object's properties with a simple loop, replace any member function with a wrapped version, attach new properties to any object ... the list goes on.

This was a calculated move on my part. I didn't have time to get everything hooked up (or upholstered ;-), so I made almost everything mutable (note how Date.prototype, the property not the object value it references, is non-configurable and non-writable; same for other built-ins). This let JS library and app authors monkeypatch and finish things.

Now, 16 years later, JS is in a bigger world, it has grown, and three things have happened:

  1. Library authors learned the hard way not to patch built-ins, unless the library is Prototype or you take Andrew's "everything is permitted" seriously (many do not).

  2. Web developers both depend on and wish to minimize the size (to zero bytes) of libraries.

  3. Programming in the large, even ignoring security, means many of us want to save ourselves from assigning to something we want non-writable and initialize-only. That's const. Or we want to avoid name collision worries, never mind hostile attacks, on private data. That's private, or else you use closures and pay some non-trivial price (verbosity and object allocation).

(3) implies adding encapsulation and integrity features, on an opt-in basis.

(2) means we keep working on the language, until it reaches some macro-apotheosis.

(1) does not imply the standard built-in constructors and their prototypes could be frozen -- don't worry about that. We won't break the web. But it suggests that users do not always need all dynamic degrees of freedom, all the time. Some, say SES users, will need to freeze their built-ins in order to build secure mash-ups. ES5 allows this. Why not?

My freedom to build a fence doesn't mean I lock the gate. But if I'm dealing with miscreants in the neighborhood, maybe I do put in a lock. Maybe I put in ice-guns and snowball launchers. My choice to do so is part of this "freedom" you advocate. Right?

# Brendan Eich (14 years ago)

On Nov 2, 2011, at 9:26 AM, John J Barton wrote:

Of course these details are important for the use-cases that need them. Unfortunately everyone else has to carry the baggage.

What exactly do you mean by "carry"?

Implementors have to implement. They get the big bucks and bear the burden for the greater good.

Most users do not have to carry all the ES5 APIs in their head. Almost no users ever even need to use Object.create. Perhaps this is a missed opportunity, but that's a different argument from what your use of "carry" implies.

# Brendan Eich (14 years ago)

On Nov 2, 2011, at 9:30 AM, Quildreen Motta wrote:

Also, note that with' makes a whole awesome use-case forObject.freeze':

'with' is gone in ES5 strict, ES6, and beyond -- you knew that, right?


with (require({'library1': 'lib1'}, {'library2': 'lib2'})) { lib1.foo(lib2.something) }

This is still hard to optimize, even with the implied freeze under require.

Also, you can't load code dynamically without nesting an event loop and violating run-to-completion, so I'm not sure how such a require would work.

This does remind me: JS's "freedom" is Dart's "cannot be tooled" and "inherent performance problems", and without aggressive optimization work it can mean JS is measurably slower for some kinds of code than Dart (or Java).

("cannot be tooled" is flat wrong, as past discussion here of static+dynamic/live-system analysis concluded.)

To "inherent performance problems", I say "feature" and "optimize harder". But it's worth mentioning, especially since you cited 'with', which is a bug that I brought ;-). Stupid-dynamic is just stupid and we should avoid it.

Freedom without fences and other tools for accountability fails at scale.

# Brendan Eich (14 years ago)

On Nov 2, 2011, at 9:46 AM, Mikeal Rogers wrote:

I agree with every sentence in this post.

+1K :)

Switching to CoffeeScript? :

# Quildreen Motta (14 years ago)

On 02/11/11 15:41, Brendan Eich wrote:

On Nov 2, 2011, at 9:26 AM, John J Barton wrote:

Of course these details are important for the use-cases that need them. Unfortunately everyone else has to carry the baggage. What exactly do you mean by "carry"?

Implementors have to implement. They get the big bucks and bear the burden for the greater good.

Most users do not have to carry all the ES5 APIs in their head. Almost no users ever even need to use Object.create. Perhaps this is a missed opportunity, but that's a different argument from what your use of "carry" implies.

Imho, no users SHOULD use Object.create directly. That's why abstractions exist — and first class functions make it easy enough to make them.

Also, there are plenty of libraries provide nice abstractions over the low-level part of the language (pd being the simplest one, I guess), to a point I think criticising a built-in feature for being "too generic" is kind of missing the point...

It's been this way with the DOOM too, isn't it?

# David Bruant (14 years ago)

Le 02/11/2011 17:05, Jeremy Ashkenas a écrit :

On Wed, Nov 2, 2011 at 11:01 AM, David Bruant <bruant.d at gmail.com <mailto:bruant.d at gmail.com>> wrote:

Could you elaborate on this point? 
All object-lockdown I can think (non-configurability,
non-writability, non-enumerability, private names, const
variables, const classes) of is optional. Why are you against them?

I was about to say "if you're unsatisfied, create a language which
doesn't provide features you don't like, like Coffeescript",
but... humm...
So, why being against the introduction of features in the language?

I'd be glad to elaborate -- but since it's off topic for minimal classes, changing the Subject here.

Thanks for your response.

What draws people to dynamic languages is freedom.

What drew people to JavaScript originally was that it was the only language of the web on the client-side. No other reason. If the language used to manipulate the DOM had been strongly typed, that's what we would be using. If from the start it had non-mutable prototype, we couldn't have fixed most browser bugs, write things like es5-shim or a bunch of other polyfills. (by the way, thanks M.Eich for including this brilliant idea in JS!)

If I had my druthers, JS.next would generally embrace the spirit of JavaScript's dynamism (and freedom), and try to push those aspects further -- with better introspection and more flexibility -- instead of compromising with more restrictive static languages and adding lock-down keywords so that some programmers might "feel safer".

Let's set arguments about security and constraint guarantees aside for a moment (although I'd be glad to have those as well)

Well, let's talk about it. Why on Earth am I forced to open an iframe to safely discuss with another script? That's such a waste of resources. And how can mutually suspicious scripts can communicate safely in JS environment where there are no iframes? Well... they can't... (with SES, now they can, but it took some time) We have accepted that people can't use scripts from different origins for the only reason that JS had no way to write programs defensively and because there is no way to take a script from somewhere else and prevent it from breaking everything.

and talk about these keywords as pure features:

"private" does not add anything new to a property. If you don't want the property to be used outside of the class ... don't use the property outside of the class.

"const" does not add anything new to a variable. If you don't want to change the value of a variable ... don't change the value of the variable.

"freeze" does not add anything new to an object. If you don't want to change the shape of an object ... don't change the shape of the object.

Following this logic, "var" does not add anything to a variable. If you don't want the variable to be used outside a function... don't use it outside the function. Are you also against "let"? it reduces even more where a variable can be accessed.

More seriously, if you're the only programmer, yes, I agree with what you said. If I give you a library, without telling you what is private and what isn't, you are likely to break the library. If I keep private what should be, you won't mess with my code. Using private variables/properties is a way for me to make sure you do not use what you shouldn't. It protects you from changes if I do internal changes to my library. The less I allow you to do, the stricter is your use of my library and the less work you need to do.

Note that Ruby, another very dynamic language, has "private" and constants. And yet private methods can be called from the outside, with "send", and contants can be explicitly overwritten with new values. They are simply red tape, not concrete walls. For better or for worse, I have very rarely seen a large-scale Ruby project that does not call a private method externally, or overwrite a constant during configuration.

If a private method can be accessed externally, well, it's not private. If you can change a constant, it is not a constant, regardless of what keyword can say.

The recent JavaScript renaissance that we're all enjoying owes debts to JavaScript's foresight as a "free", dynamic language. If all of the JavaScript core object had been frozen, locked down with private methods, and set as const properties on the global object, libraries like Prototype.js never would have happened. Libraries like jQuery would have been much more difficult to imagine. We might not have the new Array#map, #reduce, #every, or #filter methods at all.

I cannot agree more. In no way I am advocating for "locked-down by default". What I'm advocating for is "i can lock things down if I want to in my application". This is what "const", "private" and the like offer. The option for me to make my choice. I don't want locking things down. I just want the choice to do it myself in my application if I want to.

Can a free, dynamic language be abused? Certainly. Is Prototype.js dangerous? For some websites, it can be (including NYTimes.com, where I work).

The freedom of having every object and every property be configurable, settable, introspectable, readable and writable, at least at the language level, is worth the trade off. If we add const, private, and other lock-down syntax, or make class properties private by default (shudder), I guarantee you that many potential innovative libraries that otherwise might spring up will never even be conceived, and frustrating situations that could have otherwise been solved by a quick patch will instead require convoluted work-arounds.

And duck-typing also allows to work around browser bugs. I would not sacrifice that either. But in the large majority of code I have come across, the freedom is used as follow:

  1. arrange environment (duck-type to fix bugs, add things, wrap functions for logging, etc.)
  2. run your application.

If you disagree with this pattern, please provide examples. The first step uses the freedom. The second step just use the environment and created objects and doesn't mess around with existing things anymore. In this case, the benefit of locking down everything after step 1 is that it protects from mistakes or malicious code and looses no potential. Above, you mention that large-scale Ruby projects change some things during "configuration". I think it's what i describe as step 1.

In another mailing-list Mark Miller mentioned the existence of a paper that showed that 2 step pattern for Python. Is anyone aware of what paper that is?

JavaScript should be about making it easier to write the right thing, and not so much about making it harder to do the wrong thing. After all, the former is purely positive, and the latter assumes that you know better than the engineer who comes after you.In the real world, you often don't.

This is pure speculation. I could say the opposite and be as much right. In the real world, thousands of people use Java interfaces to understand what classes do and especially what they don't do. You write an interface with in mind the idea of providing a service and hiding implementation details. If an interface doesn't do what you want, inherit from it, create another interface, but there is no reason to change the interface, because the some people want the exact service it provides.

# Brendan Eich (14 years ago)

On Nov 2, 2011, at 9:51 AM, Mikeal Rogers wrote:

On Nov 2, 2011, at November 2, 20119:30 AM, Quildreen Motta wrote:

"freeze" does not add anything new to an object. If you don't want to change the shape of an object ... don't change the shape of the object. Again, immutability isn't just about security, but optimisation as well. You could also look at shared-memory threads, because I think they make a hell of an argument for "frozen" objects or immutability.

The last time we looked at freezing a few core objects in node.js we found that v8 was actually slower with them frozen and backed them out, which is probably a good thing.

I'm very skeptical of the "new language feature for optimization" argument ever since the static typing debate in ES4 and the tracer work Mozilla did shortly after.

Type inference is doing well for us now. I agree in general.

However, there's a reason Dart did what it did. With JS, you have to guard, or provide an invalidation protocol, in case someone shadows an inherited property:

var a = [], b = {m: function (i) { return i * i; }}, c = Object.create(b), d = Object.create(c);

for (var i = 0; i < BIG; i++) { a[i] = d.m(i); if (rarely(i)) { c.m = function (i) { return 42 * i; }; } }

This is a contrived case, but in general, because JS objects are mutable, and when they're used as prototypes they stand in for class vtables, something has to pay a price. Either you worry about checking on every d.m(i) call that the cached target method in b is still the one to call, or you emit code that doesn't check but tear it up and throw it away when c.m is injected and shadows b.m.

This is fine with me and worth the price, but it clearly is not for everyone. I'm not just talking about implementors, either. Some users will want to know d.m isn't going to change. They may not want to know that it's b.m, mind you -- they simply won't want that c.m assignment to be legal, or else if they do support such a thing, they don't want it to affect d's "vtable".

Ok, so such people should use another language than JS. Or, perhaps, they could freeze c and b. Then they'd have parity, once V8 and other engines got around to optimizing accordingly. (It's bogus for you to infer too much from the state of optimization vs. new features.)

# Quildreen Motta (14 years ago)

On 02/11/11 15:49, Brendan Eich wrote:

On Nov 2, 2011, at 9:30 AM, Quildreen Motta wrote:

Also, note that with' makes a whole awesome use-case forObject.freeze': 'with' is gone in ES5 strict, ES6, and beyond -- you knew that, right?

Yep, and I still think it's a sad thing. Not that I use it anyways, the performance doesn't allow me to. And we're getting real `let'.


with (require({'library1': 'lib1'}, {'library2': 'lib2'})) { lib1.foo(lib2.something) } This is still hard to optimize, even with the implied freeze under require.

Hm, not sure I understand why. I'm not a compiler writer though.

Also, you can't load code dynamically without nesting an event loop and violating run-to-completion, so I'm not sure how such a require would work.

Yes, but `require' could take a plain object out of a map or something, it could use a synchronous call. But I don't think that matters much here :3

This does remind me: JS's "freedom" is Dart's "cannot be tooled" and "inherent performance problems", and without aggressive optimization work it can mean JS is measurably slower for some kinds of code than Dart (or Java).

("cannot be tooled" is flat wrong, as past discussion here of static+dynamic/live-system analysis concluded.)

To "inherent performance problems", I say "feature" and "optimize harder". But it's worth mentioning, especially since you cited 'with', which is a bug that I brought ;-). Stupid-dynamic is just stupid and we should avoid it.

Freedom without fences and other tools for accountability fails at scale.

I still don't agree with `with' being a failure (perhaps the syntax ended up too ambiguous, yeah, and the thing about being able to change the shape of the objects and all, but...), I agree with the "optimise harder" though.

I wonder if it was the Racket guys who said that languages should indeed be dynamic, so compiler writers have more work to do :3

# John J Barton (14 years ago)

On Wed, Nov 2, 2011 at 10:51 AM, Quildreen Motta <quildreen at gmail.com> wrote:

Imho, no users SHOULD use Object.create directly. That's why abstractions exist —

Of course I agree with you!

and first class functions make it easy enough to make them.

But if we had Crockford's Object.create() rather than the one you don't want us to use we would not need the class goop ;-)

Anyway this is all wishful thinking. Languages don't get simpler.

jjb

# Brendan Eich (14 years ago)

On Nov 2, 2011, at 12:00 PM, John J Barton wrote:

On Wed, Nov 2, 2011 at 10:51 AM, Quildreen Motta <quildreen at gmail.com> wrote:

Imho, no users SHOULD use Object.create directly. That's why abstractions exist —

Of course I agree with you!

and first class functions make it easy enough to make them.

But if we had Crockford's Object.create()

You mean begetObject?

Anyway, who cares about the name? There's nothing super-magical about Object.create in my book. YMMV.

rather than the one you don't want us to use we would not need the class goop ;-)

Anyway this is all wishful thinking. Languages don't get simpler.

English is. Moods such as the subjunctive are dying, spellings grow simpler, etc.

Let's take a long view. We removed 'with' in ES5 strict and thus in Harmony. There's time to remove other things.

This doesn't mean we should "get it wrong" or be ok with less than our best, of course.

OTOH reflection/meta-programming libraries are like plumbing (or plumbers at work :-P). Why are you staring at them and worrying, when they're behind the varnished cabinet door?

When I think of "language simplicity" as a good to optimize, I think about kernel semantics and common syntax, not every corner of every built-in or standard library.

# Quildreen Motta (14 years ago)

On 02/11/11 17:00, John J Barton wrote:

On Wed, Nov 2, 2011 at 10:51 AM, Quildreen Motta<quildreen at gmail.com> wrote:

Imho, no users SHOULD use Object.create directly. That's why abstractions exist — Of course I agree with you!

and first class functions make it easy enough to make them. But if we had Crockford's Object.create() rather than the one you don't want us to use we would not need the class goop ;-)

Anyway this is all wishful thinking. Languages don't get simpler.

jjb

Racket seems simple as fuck to me :3 So does Haskell.

# James Burke (14 years ago)

Accidentally sent this only to Brendan, meant to send to list, resending:

On Wed, Nov 2, 2011 at 10:39 AM, Brendan Eich <brendan at mozilla.com> wrote:

  1. Web developers both depend on and wish to minimize the size (to zero bytes) of libraries.

  2. Programming in the large, even ignoring security, means many of us want to save ourselves from assigning to something we want non-writable and initialize-only. That's const. Or we want to avoid name collision worries, never mind hostile attacks, on private data. That's private, or else you use closures and pay some non-trivial price (verbosity and object allocation).

(3) implies adding encapsulation and integrity features, on an opt-in basis.

Does encapsulation and integrity mean adding more things to the JS language or addressing the how JS is encapsulated and run?

The SES and mashup use cases can be used as examples. Are the problems with the JS language or are they better served by securing not just JS but the DOM and network calls and having efficient containers that can communicate?

iframes/the FRAG proposal maybe, or some other JS container entity, with postMessage async passing of JSON-friendly data might be the way forward for those things.

Getting those to perform well and perhaps building better APIs around them might be more effective solutions than to adding more security/integrity features to JS syntax.

Similar to how focusing on improving the VM container to get JS to perform better was a better route than adding static type checking syntax.

The Harmony module loader API feels like another parallel. That is more of an API to a JS container of sorts with certain isolation properties. It does not necessarily mean that a JS module syntax needs to exist for that type of API to be useful.

Since it is an API, a loader API is easier to integrate into existing systems. With legacy upgrade costs (IE and even older android) and the possibility for editors to support comment-based systems that allow type and intellisense support (for quicker turnaround on a deeper set of errors than the module syntax could provide), I give a loader API a stronger chance of having a wider impact than module syntax.

(2) means we keep working on the language, until it reaches some macro-apotheosis.

In any game, it is tempting, particularly for the game designers, to try to keep tweaking the game to "get better". But that easily turns to destroying the reason the game existed in the first place, and why it became popular.

I feel that getting to zero probably means not having a successful, widely used and deployed language. This feedback is not so helpful though, right? The devil is in the details. I just needed to get it out of my system, and the mention of macros set off the "too much game tweaking" bells.

James

# Mikeal Rogers (14 years ago)

HAHA!

You'll pry JavaScript from my cold dead hands!

# Mikeal Rogers (14 years ago)

On Nov 2, 2011, at November 2, 201110:57 AM, Brendan Eich wrote:

On Nov 2, 2011, at 9:51 AM, Mikeal Rogers wrote:

On Nov 2, 2011, at November 2, 20119:30 AM, Quildreen Motta wrote:

"freeze" does not add anything new to an object. If you don't want to change the shape of an object ... don't change the shape of the object. Again, immutability isn't just about security, but optimisation as well. You could also look at shared-memory threads, because I think they make a hell of an argument for "frozen" objects or immutability.

The last time we looked at freezing a few core objects in node.js we found that v8 was actually slower with them frozen and backed them out, which is probably a good thing.

I'm very skeptical of the "new language feature for optimization" argument ever since the static typing debate in ES4 and the tracer work Mozilla did shortly after.

Type inference is doing well for us now. I agree in general.

However, there's a reason Dart did what it did. With JS, you have to guard, or provide an invalidation protocol, in case someone shadows an inherited property:

var a = [], b = {m: function (i) { return i * i; }}, c = Object.create(b), d = Object.create(c);

for (var i = 0; i < BIG; i++) { a[i] = d.m(i); if (rarely(i)) { c.m = function (i) { return 42 * i; }; } }

This is a contrived case, but in general, because JS objects are mutable, and when they're used as prototypes they stand in for class vtables, something has to pay a price. Either you worry about checking on every d.m(i) call that the cached target method in b is still the one to call, or you emit code that doesn't check but tear it up and throw it away when c.m is injected and shadows b.m.

This is fine with me and worth the price, but it clearly is not for everyone.

I don't think I've ever heard an active JavaScript developer, who has been programming in JavaScript longer than 6 months, ask for private class or instance variables. Maybe you have, you talk to more people than I do. I do hear this a lot from people who don't use JavaScript and likely won't even if we add it.

I'm not just talking about implementors, either. Some users will want to know d.m isn't going to change. They may not want to know that it's b.m, mind you -- they simply won't want that c.m assignment to be legal, or else if they do support such a thing, they don't want it to affect d's "vtable".

Ok, so such people should use another language than JS. Or, perhaps, they could freeze c and b.

I would argue that developers who rely on these kinds of assurances are actually slowing down their own, and others, productivity. Assuming they wrote the perfect method and it should never be changed is a grand claim for anyone who isn't Donald Knuth. Assuming that the consumer of their code is responsible for their own bugs if they introduce them with monkey patching class methods seems fair.

I think this is what Jeremy is getting at, not having these features (or at least obscuring their use to be a different, more explicit pattern, using closures) actually leads to longer term productivity and sustainability in the community and I tend to agree

I may have said this before, but the lack of these features may actually be part of what has allowed JavaScript to thrive and, for lack of a better term, to win. Jeremy brought up some compelling examples.

Then they'd have parity, once V8 and other engines got around to optimizing accordingly. (It's bogus for you to infer too much from the state of optimization vs. new features.)

I was just trying to debunk the claim that these features are necessarily faster and will vary with implementation. Most features can lend themselves to optimizations but, as you pointed out, at what cost.

# Kam Kasravi (14 years ago)

On Nov 2, 2011, at 1:27 PM, Mikeal Rogers <mikeal.rogers at gmail.com> wrote:

On Nov 2, 2011, at November 2, 201110:57 AM, Brendan Eich wrote:

On Nov 2, 2011, at 9:51 AM, Mikeal Rogers wrote:

On Nov 2, 2011, at November 2, 20119:30 AM, Quildreen Motta wrote:

"freeze" does not add anything new to an object. If you don't want to change the shape of an object ... don't change the shape of the object. Again, immutability isn't just about security, but optimisation as well. You could also look at shared-memory threads, because I think they make a hell of an argument for "frozen" objects or immutability.

The last time we looked at freezing a few core objects in node.js we found that v8 was actually slower with them frozen and backed them out, which is probably a good thing.

I'm very skeptical of the "new language feature for optimization" argument ever since the static typing debate in ES4 and the tracer work Mozilla did shortly after.

Type inference is doing well for us now. I agree in general.

However, there's a reason Dart did what it did. With JS, you have to guard, or provide an invalidation protocol, in case someone shadows an inherited property:

var a = [], b = {m: function (i) { return i * i; }}, c = Object.create(b), d = Object.create(c);

for (var i = 0; i < BIG; i++) { a[i] = d.m(i); if (rarely(i)) { c.m = function (i) { return 42 * i; }; } }

This is a contrived case, but in general, because JS objects are mutable, and when they're used as prototypes they stand in for class vtables, something has to pay a price. Either you worry about checking on every d.m(i) call that the cached target method in b is still the one to call, or you emit code that doesn't check but tear it up and throw it away when c.m is injected and shadows b.m.

This is fine with me and worth the price, but it clearly is not for everyone.

I don't think I've ever heard an active JavaScript developer, who has been programming in JavaScript longer than 6 months, ask for private class or instance variables. Maybe you have, you talk to more people than I do. I do hear this a lot from people who don't use JavaScript and likely won't even if we add it.

The module pattern, arguably one of the most common JS patterns out there is predicated on making internal variables 'private' via a closure, and only returning a 'public' API. For any class/type defined, there are vars that are likely to be only used within the implementation or they are vital to the class/type contract. Both are compelling reasons to have private.

# David Bruant (14 years ago)

Le 02/11/2011 21:27, Mikeal Rogers a écrit :

On Nov 2, 2011, at November 2, 201110:57 AM, Brendan Eich wrote:

This is fine with me and worth the price, but it clearly is not for everyone.

I don't think I've ever heard an active JavaScript developer, who has been programming in JavaScript longer than 6 months, ask for private class or instance variables.

Your own code: mikeal/npmjs.org/commit/c0d9cc77e79504b9a7c23b4fac735dde97444054#L3R10 Line 35, you define the function stopBuffering (keeping only relevant parts):

function File (options) {

var stopBuffering = function () { // ... }

}

Why didn't you do this.stopBuffering = function(){}?

Maybe you used the keyword "var", but you effectively created a private method of your "File" class. With a class syntax, you would have used the "private" keyword to achieve the same thing. Maybe you don't call it this way, but you use (and de facto ask for) privacy.

Maybe you have, you talk to more people than I do. I do hear this a lot from people who don't use JavaScript and likely won't even if we add it.

Who are these people? You are saying that there exists people who don't use JavaScript but want to change the language? This sounds like a crazy idea. Regardless, why should we be listening to them?

I'm not just talking about implementors, either. Some users will want to know d.m isn't going to change. They may not want to know that it's b.m, mind you -- they simply won't want that c.m assignment to be legal, or else if they do support such a thing, they don't want it to affect d's "vtable".

Ok, so such people should use another language than JS. Or, perhaps, they could freeze c and b.

I would argue that developers who rely on these kinds of assurances are actually slowing down their own, and others, productivity.

This is maybe true. For some people, productivity is not a priority. Some people want to be able to prove their program is correct, some people want security, some people want reliability and they prioritize these things higher than productivity. Should we close them the door to JavaScript?

Assuming they wrote the perfect method and it should never be changed is a grand claim for anyone who isn't Donald Knuth. Assuming that the consumer of their code is responsible for their own bugs if they introduce them with monkey patching class methods seems fair.

I think this is what Jeremy is getting at, not having these features (or at least obscuring their use to be a different, more explicit pattern, using closures) actually leads to longer term productivity and sustainability in the community and I tend to agree

This is pure speculation. I think these features won't change anything. There is a strong culture of monkey-patching and using the dynamicity in JavaScript. I think that if a library is too strongly locked-down it will be unpopular, so either people will not use it, rewrite another one with the same features or fork (if open source) and unlock. Because of the cultural aspect, people will keep things unlocked, not changing anything to long-term productivity and sustainability.

David

Ps: mikeal/npmjs.org/commit/c0d9cc77e79504b9a7c23b4fac735dde97444054#L3R64 You could do "process.nextTick( stopBuffering )" instead of creating an anonymous function.

# Mikeal Rogers (14 years ago)

This is a contrived case, but in general, because JS objects are mutable, and when they're used as prototypes they stand in for class vtables, something has to pay a price. Either you worry about checking on every d.m(i) call that the cached target method in b is still the one to call, or you emit code that doesn't check but tear it up and throw it away when c.m is injected and shadows b.m.

This is fine with me and worth the price, but it clearly is not for everyone.

I don't think I've ever heard an active JavaScript developer, who has been programming in JavaScript longer than 6 months, ask for private class or instance variables. Maybe you have, you talk to more people than I do. I do hear this a lot from people who don't use JavaScript and likely won't even if we add it.

The module pattern, arguably one of the most common JS patterns out there is predicated on making internal variables 'private' via a closure, and only returning a 'public' API. For any class/type defined, there are vars that are likely to be only used within the implementation or they are vital to the class/type contract. Both are compelling reasons to have private.

For some background, I wrote one of the revisions of the commonjs modules specification and I wrote the CouchDB implementation of that spec and I work, infrequently, on node.js' implementation.

I don't think your comparison is accurate.

You must be allowed to customize the return value of require("mymodule"), just like you can customize the return value of a function call, and require() is a function call.

While it may not be obvious to the user, the reason the scope is private by default is because you have to do a function wrapped eval in order to allow customization of the return value from require(), not the other way around as your comment would suggest.

The fact that module variables and methods default to private is actually a source of pain. For example, we have exposed previously internal objects and methods to the exports object in bugfix releases of node.js because there was no other way to work around a bug or customize important or broken behavior. The fact that they weren't public by default means that we now have forward incompatibility problems in point releases of node.js.

If every js implementation had an eval sandbox where we could pass in and return a new scope commonjs modules may have done that by default and only made that scope private when the user intended to customize the return value. I would have advocated it, but commonjs modules had to be written for the lowest common denominator so that was never an option. In fact, the commonjs spec can't even support node.js' module.exports = function () {} because it can't work in some environments.

# Jake Verbaten (14 years ago)

I don't think I've ever heard an active JavaScript developer, who has been programming in JavaScript longer than 6 months, ask for private class or instance variables.

Your own code:

mikeal/npmjs.org/commit/c0d9cc77e79504b9a7c23b4fac735dde97444054#L3R10 Line 35, you define the function stopBuffering (keeping only relevant parts):

function File (options) {

var stopBuffering = function () { // ... }

}

Why didn't you do this.stopBuffering = function(){}?

Maybe you used the keyword "var", but you effectively created a private method of your "File" class. With a class syntax, you would have used the "private" keyword to achieve the same thing. Maybe you don't call it this way, but you use (and de facto ask for) privacy.

I think making such broad statements as "every local variable is actually a 'private' variable" is just plain silly.

To me that looks like a utility method for code organisation points.

"private" means its a private method/data that's used in other methods of an object. That particular function is not used in any method.

And no, with class syntax it would not be private, it would still be a utility function inside the constructor.

I personally second that we don't need private or instance variables.

# Kam Kasravi (14 years ago)

Declaring vars in a function, private vars in a class or not using export in a module often have similar objectives and ultimately is the decision of the author. For serializable data structures that are reified in various places, private is overkill and would complicate JSON.{stringify,parse}. Perhaps an author wants to keep a definition 'open' and sees no reason for private. The language should enable but not require a variety of use cases which I think is the main point here.

# David Bruant (14 years ago)

Le 02/11/2011 22:56, Jake Verbaten a écrit :

I don't think I've ever heard an active JavaScript developer, who
has been programming in JavaScript longer than 6 months, ask for
private class or instance variables.
Your own code:
https://github.com/mikeal/npmjs.org/commit/c0d9cc77e79504b9a7c23b4fac735dde97444054#L3R10
Line 35, you define the function stopBuffering (keeping only
relevant parts):
----
function File (options) {

  var stopBuffering = function () {
    // ...
  }

}
----
Why didn't you do this.stopBuffering = function(){}?

Maybe you used the keyword "var", but you effectively created a
private method of your "File" class. With a class syntax, you
would have used the "private" keyword to achieve the same thing.
Maybe you don't call it this way, but you use (and de facto ask
for) privacy.

I think making such broad statements as "every local variable is actually a 'private' variable" is just plain silly.

What is the difference between a local variable and a private object property? Both reduce access to the data they store. Private properties are only accessible from the body of a given number of functions, local variables too. What is the difference? I don't get why we would push 'let' to ES.next and not private properties.

To me that looks like a utility method for code organisation points.

"private" means its a private method/data that's used in other methods of an object. That particular function is not used in any method.

And no, with class syntax it would not be private, it would still be a utility function inside the constructor.

You're right, I didn't analyse the code enough. Sorry, my mistake. But my point remains. Why make a "utility function"? What is "utility"? Why isn't it public like everything else?

# Brendan Eich (14 years ago)

On Nov 2, 2011, at 1:27 PM, Mikeal Rogers wrote:

On Nov 2, 2011, at November 2, 201110:57 AM, Brendan Eich wrote:

[vtables vs. prototype properties performance stuff deleted]

This is a contrived case, but in general, because JS objects are mutable, and when they're used as prototypes they stand in for class vtables, something has to pay a price. Either you worry about checking on every d.m(i) call that the cached target method in b is still the one to call, or you emit code that doesn't check but tear it up and throw it away when c.m is injected and shadows b.m.

This is fine with me and worth the price, but it clearly is not for everyone.

I don't think I've ever heard an active JavaScript developer, who has been programming in JavaScript longer than 6 months, ask for private class or instance variables.

Why are you talking about private when I was talking about performance issues that might or might not be helped by freeze, seal, and const?

Maybe you have, you talk to more people than I do. I do hear this a lot from people who don't use JavaScript and likely won't even if we add it.

There are lots of people using the closure pattern precisely to have private instance variables. Crock's thin little book recommends it.

I'm not just talking about implementors, either. Some users will want to know d.m isn't going to change. They may not want to know that it's b.m, mind you -- they simply won't want that c.m assignment to be legal, or else if they do support such a thing, they don't want it to affect d's "vtable".

Ok, so such people should use another language than JS. Or, perhaps, they could freeze c and b.

I would argue that developers who rely on these kinds of assurances are actually slowing down their own, and others, productivity. Assuming they wrote the perfect method and it should never be changed is a grand claim for anyone who isn't Donald Knuth. Assuming that the consumer of their code is responsible for their own bugs if they introduce them with monkey patching class methods seems fair.

Of course I agree, but one size does not fit all in JS. Again, "freedom" includes my ability to fence my yard.

If there's an enclosure movement, where the new lords of the land (who stole it fair and square) kick off the tenant farmers and close the commons, then we have a fight and I'm on the same side as you. But that's not what is threatened by providing fencing material and tools. Tools are not moral actors.

And really, who is going to enclose the commons and freeze everything? Google? Hah!

I think this is what Jeremy is getting at, not having these features (or at least obscuring their use to be a different, more explicit pattern, using closures) actually leads to longer term productivity and sustainability in the community and I tend to agree

I may have said this before, but the lack of these features may actually be part of what has allowed JavaScript to thrive and, for lack of a better term, to win. Jeremy brought up some compelling examples.

I am sure JS has thrived in part because I chose to make it monkey-patchable, but providing integrity features on an opt-in basis does not mean JS won't thrive. It might mean those users who in the future opt into freezing, etc. and make the world too cold find the users have gone to warmer climes on github. That'll be even more convincing proof of your conjecture.

Then they'd have parity, once V8 and other engines got around to optimizing accordingly. (It's bogus for you to infer too much from the state of optimization vs. new features.)

I was just trying to debunk the claim that these features are necessarily faster and will vary with implementation. Most features can lend themselves to optimizations but, as you pointed out, at what cost.

The VM game continues. My argument in favor of optional integrity features is not about performance, but performance can get better with more lock-down. Again see Dart and the bragging about it compared to JS. Not that this should matter or prevail forever!

# Claus Reinke (14 years ago)

I'm not just talking about implementors, either. Some users will want to know d.m isn't going to change. They may not want to know that it's b.m, mind you -- they simply won't want that c.m assignment to be legal, or else if they do support such a thing, they don't want it to affect d's "vtable".

I would argue that developers who rely on these kinds of assurances are actually slowing down their own, and others, productivity. Assuming they wrote the perfect method and it should never be changed is a grand claim for anyone who isn't Donald Knuth. Assuming that the consumer of their code is responsible for their own bugs if they introduce them with monkey patching class methods seems fair.

Ok, I have to wade in here: if you cannot see why some people want such features, why are you arguing against these features?

[the "you" here is not (exclusively) about you, but about a pattern often exhibited by vocal and repeated opposition to things:-)]

The Javascript user base is huge, with obviously different views, and this doesn't seem to be your discussion to have, does it?

You could try to argue that warnings are better to have than errors in Javascript, eg, it should be easy to spot if someone is interfering with your code's base assumptions, but you don't want that to stop you from running that code anyway, knowing that doing so might be unsafe.

Example: the switch from warnings to errors for non-essential features of JSLint meant that many JS coders can no longer use JSLint, so the switch actually reduced its effectiveness.

So, if a proposed feature interferes with your use of the language, state that interference, and perhaps the proposals can be changed to accommodate your concerns. That is a discussion based on technical issues, which can make progress and can achieve targets.

However, you might consider how your personal perspective affects your judgement:

  • if you're developing node, you're at the start of the chain, no-one can interfere with your definitions

  • if you're developing node libraries, you have to keep up with node only, but you have to do that anyway

  • if you're using libraries from a single source only, you're still not likely to be affected, because those libraries are either consistent or have a bug that needs fixing

  • if you're using libraries from several sources, you're suddenly open to a lot of trouble, as any library from source A might interfere with base assumptions made by any library from source B

  • if you're browsing the web, where many pages include code from dozens of sources, you're out of luck quickly if you cannot see what is conflicting with what

  • if you're in the business of trying to ensure that web users won't run into trouble, you want to pin down what each page widget and ad module is allowed to do (whitelisting); and if you take that to its conclusion, you need to base your whitelisting in the language

I could go on about how types can be a tool, not an obstacle, if zealotry can be avoided, or about how many (most?) people who are well-known for doing reflective language features (the stuff "dynamic" fans like most about JS) have expressed the opinion (later in life, based on experience with their systems) that reflective and normal use should be separated as clearly as possible.

But I really just wanted to say: don't argue against features you do not need, argue for features (or changes of features) you do need.

If a feature you do not need interferes with something you do need, that is a bug in the feature that should be pinned down and addressed (dismissing the whole feature won't help, unless the problem is unavoidably tied to the feature).

If a feature you do not care about takes resources you would like to see spent on something you do care about, that may be a bug in the process that

Just another opinion from another JS coder.

Btw, some message to es-discuss are still missing, and es-discuss-owner has not replied.

Claus clausreinke.github.com, clausreinke.github.com/js-tools

# Quildreen Motta (14 years ago)

I think Claus summarizes nicely what I've been thinking about this thread, and the opposition-for-the-sake-of-opposition that has been spreading through the JavaScript community. Though most of that seems to be based on "JavaScript should be kept simple." I'd argue there doesn't need to be conflicts between expressivity and simplicity. Remember, your concepts of expressivity might not be the same as my concepts of expressivity, just as the way you approach a certain problem might not be the same as the way person B and C approach a certain problem.

And given that the methods to solve a problem doesn't immediately qualify something as "bad" or "wrong", if we can reach a common ground on what group A needs for expressing their ideas, and what group B needs for expressing their ideas, why shouldn't we? It's only a problem if said features clearly reduce the expressivity of the language for a certain group of users considerably (and that's when you should say it does, so people working in the language can do better iterations on the particular feature design), and I don't see it as being the case for const, private or frozen objects, tbh.

JavaScript is a huge language, it's used by several people, and used to solve several kinds of problems. Different problems need different features, they need better syntax too -- that's why DSLs are lovely, and why people keep creating them even though you could just as well write everything in C. So, if instead of making a language "one-size-fits-all" that's geared towards solving only a particular problem well, if we can give people different flavours of the language by features that don't conflict, or don't make the language a pain to everyone else, I think that's something worth seeking.

Of course, we can't please everyone -- and I'm not saying we should, -- after all, languages are inherently biased. But that doesn't mean we can't give people better tools for solving new problems. Isn't that what programming is all about, anyways? :3

2011/11/3 Claus Reinke <claus.reinke at talk21.com>

# Harutyun Amirjanyan (14 years ago)

"freedom" includes my ability to fence my yard.

yep, but that fence can't be removed ever after. and if there are irremovable fences, it's important to make sure, they do not rise by themselves.

e.g. requiring "public" (thanks for not doing that:) freezing module scope. adding better syntax for @private variables (private variables in closures already have advantage by not needing "this.") are all luring people to build fences they don't need.

to keep game fair, not building a fence should be at least as easy as building one.

# Brendan Eich (14 years ago)

On Nov 3, 2011, at 1:56 PM, Harutyun Amirjanyan wrote:

"freedom" includes my ability to fence my yard. yep, but that fence can't be removed ever after. and if there are irremovable fences, it's important to make sure, they do not rise by themselves.

That's completely false. If my "fence" is a frozen object, I can remove the Object.freeze call later. My source can be forked to remove it sooner.

To follow the analogy, what you are insisting on is the right to take down my fence while I'm still living on my property.

e.g. requiring "public" (thanks for not doing that:)

A different kind of public is in the latest gist, but it may not make it. It's simply to enable @foo instead of this.foo. It is not strictly necessary, per @mythz.

freezing module scope.

Modules are not objects primarily, although they reflect as sealed objects. This gives early errors on typo'ed or otherwise mismatched exports/import mismatches.

adding better syntax for @private variables (private variables in closures already have advantage by not needing "this.") are all luring people to build fences they don't need.

Closure pattern is fine for private variables until it scales to the point that the closure per method per object cost is too high. Then what?

BTW, a closure is a fence that you can never take down without a code rewrite (not just removing an Object.freeze call).

to keep game fair, not building a fence should be at least as easy as building one.

That was never in dispute, since JS is so dynamic.

I think the idea that my ability to build and maintain fences -- or even walls in my house -- limits others' freedom is a fraud. It's anti-freedom.