Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Loyal Opposition to Const, Private, Freeze, Non-Configurable, Non-Writable... (mail.mozilla.org)
81 points by tswicegood on Nov 2, 2011 | hide | past | favorite | 51 comments


  "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've got a better idea: how about we mark the variable in some way and get the compiler to remember this for us. Then, when we come back to the code in 6 months, we won't make mistakes.

I have a decade of experience in "dynamically" typed languages, and I prefer modern statically typed languages in almost all situations. Now it turns out you can have both: see Racket and Typed Racket for instance.


Absolutely. I don't to have to remember which variables are safe to change and which ones aren't; I want the language to remember that, and to remind me if I get it wrong.

Sometimes I might want to use a library in a way its author didn't previously intend, so I might then want to modify a variable even if it's marked as const. It makes sense in a dynamic language to have a way to bypass the checks (like Ruby's "send" to access a private method). But that isn't an argument for discarding checks altogether.


"I've got a better idea: how about we mark the variable in some way" — if all you need is a mark, the Python convention to add an underscore in front of your private method or variable works just fine, as does the convention to make constants uppercased. I've seen quite a bit of JS code use these conventions too.

The trouble with true private/protected variables is that you never really know how your code is going to get used and which parts of your library people may want to mess with. In that case, you can either play around with things you aren't really supposed to touch, or if that's not possible because everything's encapsulated, being in a hurry, you'll just fork the code and turn private methods into public ones. Both approaches suck, and the problem exists regardless of whether your language supports `private` and `const` keywords or not.


"if all you need is a mark, the Python convention to add an underscore in front of your private method or variable works just fine, as does the convention to make constants uppercased. I've seen quite a bit of JS code use these conventions too."

Until you have a user subclass your class and accidentally stomp over one of your private names, causing your class to mysteriously fail. I've been bitten by this before, and it'd be nice for JS to offer a solution.


I'm somewhat of two minds about this.

On the one hand, I think he has a point that said features of JS.next are cutting against the grain of present-day JS. There are quite a lot of people programming in JS, many of whom may or may not deserve to be called good programmers but who nonetheless can produce functioning web pages, that would have to switch to a very different coding model to work with JS using these new features.

On the other hand, it's difficult to program your code when you know than any of your invariants can be accidentally stomped on by any other code that happens to run on the same page. It's also difficult to write libraries when everything's guts are exposed, even with red tape. Raymond Chen over at MSFT has an entire blog that could be titled "How Implementation Details Become De Facto Interfaces Due to Insufficient Encapsulation."

I think my final thought on the matter, is that when you think about it, it's really quite silly that we only have one language for front-end web development. It is, in fact, unacceptably silly. Like, seriously guys, what the hell? This is totally crazy. If you want to do server work, or non-web client applications, or embedded, or whatever else, you have a full array of programming languages. These run the gamut from ball-gag-and-leather-straitjacket static languages to walk-into-anyone's-house-and-drink-their-milk dynamic languages, from concise expressive languages to low-level bit-fiddly-ones, from parens to curly braces to significant whitespace to perl.

On the web we have JavaScript. Not that it's a bad language, it has its warts (what doesn't?) but it's actually a cute little language. But I don't have the option of using a language with static guarantees. Or deterministic memory management. Or asynchrony. Or macros. None of these are strictly better, they're all just personal preferences, but the point is, you don't have the choice.

That lack of choice is probably what's driving these against-the-grain additions to JS.next. They're adding more features to JavaScript so that it can cover some of the bases that it currently doesn't, and all the different directions it's being pulled in are understandably causing some stress. I think it's the wrong solution, but it's also the one with the easiest transition path. The ideal solution, is that we could use different languages from different paradigms, but how the hell do you crowbar them into existing browsers?

So uh... do I have conclusion? I dunno, language evolution is hard, let's go shopping.


If Google adds a Dart VM to Chrome, they'll at least have crowbarred some different language into the browser. A completely useless language that won't change anything substantial on its own, but still. Maybe it will lead to some important developments.


It doesn't need to be "either move in the direction of total dynamism or move in the direction of static guarantees".

At the very extreme end of total dynamism, you get facility to implement whatever kinds of guarantees you want as libraries. Sad that in a language without meta programming features, the power is indeed reduced, but nevertheless extreme dynamism can be powerful enough to implement the guarantees that you need.

For example, if JS gets a facility to "run this code when an unknown method of this object gets called" and "-ditto- when an unknown field gets set or read", you can implement a public API for an object using a proxy object. You'll also be able to enforce member naming conventions if you want to. If you're doing the wrapper only for checking, you can keep the wrapper during development and leave it out when you deploy the code. You get a lot of flexibility.

Furthermore, if JS lets you install hooks like python decorators, you can implement guarantee mechanisms in JS as a library similar to what decorators get used for. Again, if it gets you better performance, you can strip decorators from deployed code during the minification phase.

So indeed, why not shoot for extreme dynamism in JS?


Being able to declare member variables as private (really private, not the private alluded to in Ruby) is good. As the OP said, you don't have to declare a member variable as private if you want relaxed 0constraints. But when you want to for good design reasons -- it's great that the language you are working with allows you to do so.


If you really need private member variables you can probably whip something up with lambdas, though it might be a little awkward.


It's super easy:

  function A {
    var secret = 0; // <---------- private variable
    this.method = function() {
      alert(secret);
    };
    this.increment = function() {
      secret++;
    };
  }

  a = new A();
  a.increment();
  a.method(); <-------- prints 1
The main problem is just the inefficiency of declaring methods inside constructors.

Edit: Hence, the keyword.


jashkenas is one of the most prolific and talented JS devs around (CoffeeScript, backbone.js, underscore, docco are among his credits). I can see why he and other library producers would want as much flexibility in the language as possible.

Library consumers, on the other hand, will reap the most benefit from the proposed constraints.

`private` is important metadata for a library consumer. Documentation generators can ignore private members, and private tags serve as roadsigns that the member can be ignored if one is only interested in the API. `private` is a very powerful filter.

The same can be said for `const`: indicating a value shouldn't change eliminates one more thing one needs to hold in their head as they explore a lib's boundaries.

I don't care at all about the performance benefits; I care about communication. `private` and `const` are nearly-free, expressive documentation.

I actually like Ruby's "red tape" approach; it offers library consumers helpful metadata while still allowing flexibility. Maybe the best solution is for library developers to rigorously use the _private and CONST naming conventions, and reserve `private`, `const`, and `freeze` for security-sensitive code. Wouldn't that offer the most flexibility?


To be honest, there are very few languages where 'private' and 'const' modifiers can't be gotten around. That doesn't decrease their usefulness though if people agree to code to the spirit of the language's design.


This is similar to the divide I see in the PHP community.

There's been such a big movement towards more strictness, more Java-like features and frameworks, while the more interesting development today seems to be moving away from that, towards more concise, flexible, and expressive languages like Ruby and Python, more FP ideas, and the rise of server-side Javascript.

I started programming professionally in Perl, where you were handed a loaded gun and learned the hard way not to shoot yourself in the foot. I appreciate the discipline that demands, making you think hard about what you're doing.

I really hope the Javascript community doesn't start to compromise its dynamic nature and lose one of the things that made it great. There are areas where syntax could certainly be improved/made more concise, but keep the dynamism and flexibility all the way (and add more!). Good on Jeremy for fighting for that.


My general feeling is that these un-features take things away, and what they purport to provide in exchange is fewer bugs by virtue of being able to check certain constraints at ‘compile time’.

I’m all for taking things away, but I personally want more in exchange. For example, if you’re going to give me immutable or const declarations, give me lazy evaluation as part of the bargain.

So I’m not opposed to taking things away, I am just optimistic that we can provide a lot more value than ‘constraints’ in exchange. And if we aren’t going to provide more value, I think we’re setting our sights too low.


Have you considered the value that these keywords add to a team environment, or as reminders when visiting an api that you haven't worked on in months? It's something a little more standardized than "_privateVar" and "maxCount =4; // NOTE: Constant Variable!"


I have, and speaking as a guy who spent a big chunk of his career working with large teams on large code bases, I think private and const are small potatoes next to really big domain-specific semantic constraints. So to me, providing small value in exchange for making other things harder to do is not a win.

It feels like we're circling around a local maximum and nobody is trying to make a really big leap when thinking about JS.next. We're getting the warmed-over leavings of middle-of-the-road language ideas.

If you really want constraints that are tailored for a team environment, make them programmable and put const and private in the standard lib. Then let Alice write something that prevents Bob from putting text in a SQL query or opening up an XSS vector in raw HTML. Or let Carol write something that ensures that all code makng certain writes to the database have an authorization check baked in.


Thanks. Contracts are an AWESOME idea and I would love to see them make it into a language that everyone uses.

The ideas behind powerful contracts / type systems have been around for a long time: provide properties that are checked such that you can rely on them.

It seems an interesting and difficult problem to try to add a general enough contract system to javascript, which would support things like const and private and "account balance is always positive". But I think that if done well, it would be the single defining feature which would draw me into using a language. Man, would that be awesome.


Not sure if const/private are a good fit for contracts but things like "account balance is always positive" can be done right now with contracts.coffee using object invariants. For example, verifying the invariants of a binary search tree hold [1].

[1] http://disnetdev.com/contracts.coffee/#duck


You just made me look seriously into coffeescript. Thanks!


FYI, http://disnetdev.com/contracts.coffee/ is built on ES6 proxies and CoffeeScript.

I agree on circling a local maximum, but some of this is just JS catching up to Ruby and Python. Syntactic affordances for usability that desugar to only lightly extended kernel semantics.

The big ticket items are modules, proxies, weak maps, binary data, and the like.

When I liken JS to x86, I'm not comparing it to assembly so much as to a ubiquitous target for compilation. JS is even stickier and longer-lived than x86 -- witness ARM's rise on mobile while the web evolves mostly-compatibly, including JS content and the JS language.

Contracts and macros are on the Harmony agenda, further out.


I came across contracts some time ago and found it very appealing and inspiring, but for all my professional projects I am successfully using my own library schema.js ( https://github.com/akidee/schema.js ) - you can use it in pure JavaScript, too. (Usually I do not validate forms on the client-side, since the data must be validated on the server-side anyway. And with schema.js, you can add custom localized error messages.) Furthermore, schema.js has several modes that allow tolerant adaptation of values, so that they can be casted. "5", for example, is casted to 5. But you can switch to strict validation mode as well. You can do everything, that contracts allows, with schema.js, too. The best is that, with JSON schema, 1) you define secure validations, since with the default properties you do not forget important constraints, and 2) you do not need to test your validators any more. Conclusion: I agree that such features must make it to the core of a language. Probably you can find some useful ideas in JSON schema and schema.js. I found the JSON vocabulary to be very useful to validate JS data.


Thanks, I like Design By Contract(tm) and this looks very interesting.


As a long time writer of JavaScript I say bring it on. If you want JavaScript to succeed outside client browsers in a big way you must to consider performance. If it wasn't for incredible perf gains in the past couple of years you would not see JavaScript pushing into the server side.

However JavaScript performance still leaves much to be desired - http://stackoverflow.com/questions/6216888/is-nodejs-faster-....

I want JavaScript to close the gap without sacrificing dynamism. And it won't - these feature are entirely optional and they free the implementors to make assumptions which allow further optimization.

"Pay for what you use"

To be totally honest I don't see myself writing plain JavaScript much longer, I'm closing in on 7 years now. At work I use quite a bit of CoffeeScript and very likely in the near future I'll leverage ClojureScript.


Why not allow for C extensions to Javascript, and create a compiler capable of easy generation of these extensions with optional typing?

An example of this would be Cython for Python, which lets you get to C speed within 1 to 5% slow down due to interfacing with Python, and it has you write in a Pythonic dialect of C/C++.


Because, all else being equal, writing your code in one language is better than writing your code in two languages.


Why not allow for C extensions to Javascript...

Because that's a terrible, stop-gap optimization strategy. You can't JIT over the FFI boundary without some heroic API, and distributing compiled/compilable code is quite a hassle.


> "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 think the author missed the point of private, because it does add something new. Specifically, it adds the ability to know that the property is not being altered outside the class without reading the entire code base.


Not even reviewing the code can prove that any property is inaccessible, when its name could be constructed anywhere at runtime and used via object[propName]. Without actual language and runtime enforcement, there are almost no pervasive changes safe enough to make without the kind of thorough regression testing most teams aren't prepared to do. Which is not to say they don't do it anyway, and sometimes get lucky.


I've done a lot of low-level JavaScript work via my time developing SproutCore 1.0.

Jeremy is right on. Keep JavaScript open. Add red tape if you must, but don't ACTUALLY lock it down. The openness (and lack of package management) are killer features.

We are lucky that JavaScript is the language in the browser; it could easily have been Visual Basic (shudder).


He seems to be under the misapprehension that libraries would be impossible or extremely difficult if you added restrictions to the language. This is illogical. Languages with many more restrictions, like Haskell, can still have useful libraries. Sure, jquery wouldn't be able to work in exactly the same way it does now, but it could still work. (I would imagine wrapping objects instead of actually changing their prototypes).

Also, he doesn't go over the most useful aspect of static OO, which is interfaces. Being able to force an incoming argument to have attached methods often makes code much simpler, because you don't have to deal with the possibility of someone passing different arguments into your function.

Arguments like this usually degenerate into shouting messages, so I would like to conclude that even though I am a huge fan of static typing, I don't think it's for javascript. You can always add a static type checker on top of a non-static langauge, so people like me will be happy. It might be more difficult to go the other way around.


> He seems to be under the misapprehension that libraries would be impossible or extremely difficult if you added restrictions to the language.

It seems to me that the restrictions he's talking about adding to the language are akin to making JS closer to Java, not closer to Haskell. Those similar restrictions - in Java - make extending an existing library much more difficult since you can't do things like add methods to an existing class/object; that method has to exist elsewhere & take the object you're extending as a parameter. This isn't an issue in Haskell since functions don't exist on an object, but are defined outside the types & operate on them.


Of course I have never programmed in Haskell, so perhaps I am showing my ignorance, but my impression of Haskell is that it has all of the type restrictions of java plus many, many more. My point is that a language like Haskell (or Java, take your pick), can still have easy to use libraries written for it.

Sure, you can't change the methods of a class has at run time. Who cares? Like I said you can just create an object wrapper, sometimes called a decorator if you are into design patterns, that has all of the methods of the original object plus a few more (or even a few less, doesn't matter). This gives you all of the functions of the original object plus more, just like modifying a class at runtime does. Possible in Java, possible in Haskell, possible even in JavaScript.

The only difference is that you have to explicitly call into the wrapper classes. You can't expect objects that you instantiate from outside your library to have these methods.

But again, who cares. If you want to use the cool new library functions, use them. Otherwise don't.

Specific example: if we are talking about jquery, you can't expect document.GetElementById('foo') to have special jquery functions. But you can expect $('#foo') to have them, which is the same thing so you really have nothing to complain about.


I think Jeremy's real point is that Javascript is an entirely different beast than Haskell or Java or Ruby. Why? Javascript depends on a free and open code environment to get around the fact that the actual language's development moves glacially, you have no control of the deploy environment (unless you are a browser developer or are working in node) and it is not easy to manage large projects (inclusion and namespacing features are lacking or limited in JS). In fact, the only feature that allows JS to keep up at all with these other languages is that it tells its developers "Look, I don't have a lot of fancy features and I haven't really changed in about a decade, but I'm entirely open. Hack and abuse me at your pleasure, codify me if you must, I'll take it. I always do."

None of the proposed object-lockdown would prevent anything. You could use decorators, you could use an adapter, hell you could rewrite or fork the useful library and take out the object-locks. But all of those introduce the very overhead that JS benefits from avoiding. I mean compare the size of "Javascript Pattern" to the GOF book. What's more, languages like Java are written with a sensitivity toward design patterning, Haskell has robust types/interfaces. Javascript just has a big empty box, prototypes and closures. (This is an exaggeration but if you declaim it loudly enough you will get a chuckle.)


Hey, jQuery's just a monad. It would be easy to express in Haskell :)

[Also: if you have used jQuery, you've used a monad. They aren't scary!]



As far as I can tell, this rebuttal... isn't. The author just completely misread the original argument.

EDIT: Example: "in particular, how a monad must be capable of "wrapping" (their terminology) arbitrary datatypes, not just one particular datatype"

Yet it was very clear the author was talking about wrapping arbitrary types and IO String was a single example. And it goes on...


I'm not sure where the opposition to private is coming from, outside of being anti-additional-syntax. Private variables already exist in Javascript. They're just inefficient, because they mean that any of an object's instance methods that reference them have to be declared inside of the class's constructor function, instead of on the prototype.

Private variables may be accessible outside of classes in Ruby -- but they already aren't in JS. And JS has extremely strong encapsulation through scoping and closures, so arguments against encapsulation based on the "language grain" fall a little flat for me. If an explicit private keyword enables optimization of existing functionality, then why not have one?


> 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.

If you say so.


I've been asking a lot of dumb questions today, so here's another: Do we have any decent tools to measure memory usage / allocation when running a Javascript program?

Once we start introducing these data structures we will have to figure out actual memory storing (16bit? 32bit? 64bit?) which obviously introduces another layer of complexity to "standardizing".


I think my biggest problem with the "if you don't want X to happen, then don't do X" statement is that it only makes sense in the context of working as an individual who controls all possible moving parts. It doesn't make sense (at least, for me) in the context of a team.


I've noticed that people are always trying to outsource code review to the computer.

In my experience, no compiler is sufficiently intelligent to outsource this to. And if you have to review the code anyway (and you do), enforcing coding conventions is the least of your problems.


Doesn't seem like many people are considering the "security" benefits of having private, constant and frozen.

Being able to freeze an object to prevent anything modifying it would be useful for preventing 3rd party scripts you include on your site from deleting or modifying your code's behavior.


So is proper namespacing.


Having thought about what you meant... Even with namespacing you still have a global object that can be maliciously overridden or modified


If an attacker is in a position to make malicious modifications 1) You've got a larger problem than optional language features on your hand and 2) locking down a few properties (or the entire object) isn't going to save you.


From your example below: think of one of those ad network scripts (or any other 3rd party script you include on your page) you have no control over what that code is doing. It could override any of your global objects


This is accurate regardless of language features. You can't control 3rd party code. Using generic object names greatly increases the odds that at some point you're going to run into a namespace collision and something important will be overwritten. Proper object namespacing your objects vastly decreases the odds of this happening with benign 3rd party scripts, no additional language features required.


I'm not sure what you mean by that?


Back when I was working for the newspaper industry 3rd party scripts where a constant headache. Due to some severe limitations of the CMS the company used, we where relying on a devil's brew of vendor-supplied js to drive forums, commenting, mail-a-friend and blogging.

This was in addition to all of the script pulled in from ad networks, inline crap that was shoehorned in by a newspapers' own developers, all of our in-house stuff, various frameworks with the usual add-on libraries, analytics, maps....imagine if you will 16 meg page weights on a site with minimal graphics.

Needless to say this rolling clusterfuck of 3rd party javascript meant that at least twice a week a site would go haywire when some random code snippet from an ad network stomped all over one or more critical variables for the commenting system, or analytics would run off into the bushes for no readily discernable reason, you get the idea.

The Solution: aggressively namespace all of the mission-critical scripts we controlled and go heavy on encapsulation. Sure, this lead to god object code smells, but it cut way down on javascript-related site outages.


From the article: ""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. "

Now, having started to dabble a little in Rails and Node--and hence getting exposure to Ruby and JS--I do have respect for a lot of the interesting things you can do in those languages.

That said, I've also got a experience dealing with libraries and software engineering on various sized projects, and I'm sensing a pattern here.

It seems like good practices (encapsulation, static typing, etc.) are being ignored because they get in the way of "free programming". Now, is this actually an accepted attitude in the web development world, or are these people actively promoting terrible design practices?

I understand that programming routines for web pages and the like is not the same as for thick-client applications, but is the use of your library by other people through an interface or namespace collisions really not a large concern?


The recent JavaScript renaissance that we're all enjoying owes debts to JavaScript's foresight as a "free", dynamic language.

Bollocks. If javascript wasn't the language of browsers, nobody would use it. Its got nothing to do with javascripts awesomeness. Indeed, that it took so long for the community (or in this case Mozilla and Google) to finally say "fuck it, this is the shitbag we're stuck with so at least lets make it faster", just tells me how much they wanted something else to be the standard.

The only argument for NodeJs etc is that programmers can code the same language on client and server. Was there some "foresight" that made javascript the language of browsers? No.

That said, why fuck with it? There are ways to encapsulate fields and methods in javascript. There are also ways to get around it. Just as there are ways to get around private and const in C++.

If private and const really float your boat use GWT.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: