Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
The Future of JavaScript (chromium.org)
170 points by JoshTriplett on Feb 10, 2012 | hide | past | favorite | 109 comments


I'm probably alone in saying this, but I hope most of this stuff never sees the light of day.

What makes JS powerful is its simplicity. "var" or no "var" gets you local or global scope. Done. Want a constant? Make a global variable and don't change it. Want to really make sure its unchangeable? Make an accessor function.

Scope in JS is very simple to understand and quite versatile once understood. Adding more layers of complexity does not help.

One of the strengths of js is that every thing is an object(almost). So the bit about "no more need to abuse objects as dictionaries" is a bit odd. Since most things are objects, you get the power to treat functions, types, literals, etc in interesting ways.

One of the strengths of object literals is that you can use them as dictionaries. obj.foo === obj['foo'].

I love getters/setters and some other improvements like strict mode. However I am very much against what seems like an unnecessary cluttering of the language without fixing some of the long standing problems like ==/===. For me, I almost never use == so it should be gotten rid of. Make == === === for example.


> One of the strengths of object literals is that you can use them as dictionaries. obj.foo === obj['foo'].

I believe Harmony sets allow you to use any object as a key, whereas using a plain JavaScript Object instance will coerce the key to a string and use that as a key. There is no non-hacky way to do this in JavaScript currently. You either need to us an array (making lookups O(n)), or give objects a UID to use as the key.

Even if you're just talking about sets with strings as keys, there are lots of edge cases waiting to bite non-experts. For example, what if you want your set to have a key called "toString"? Every JavaScript object already has that method, so if you naively test "set[key] !== undefined" or "key in set" with "toString" as the key you always get true. Ok, so use "set.hasOwnProperty(key)". Now what if you happen to have a key called "hasOwnProperty" and you mask the builtin function? So really you should be using "Object.prototype.hasOwnProperty.call(set, key)". Additionally, now you're making a function call, which could add significant overhead in tight loops.


I don't think this makes scope in JS much more complicated. If you were teaching JavaScript to someone, you'd either not mention let (if old browsers still matter), or not mention "var". You wouldn't ever need to tell a newbie about both. "const" is extra, but is it really so complex?

>One of the strengths of object literals is that you can use them as dictionaries. obj.foo === obj['foo'].

That's not a strength when it means you can't use anything other than strings as keys. It destroys your ability to 'treat functions, types, literals, etc in interesting ways' if those interesting ways involve using them as dictionary keys.

>For me, I almost never use == so it should be gotten rid of.

Backwards compatibility.


In my experience, the charm of simplicity of JS starts fading away when you start moving away from DOM manipulation and start writing complex objects. Just last week I ran into the lexical scoping issue ( I was not aware of it before) that had me scratching my head for hours. Scoping in JS becomes less fun the deeper you start digging. I am glad that they are aware of it and are actively trying to address it.


I agree with geuis, and I've written a personal-use JS framework that's in the same ballpark as jquery. I've run into the lexical scoping issue, but not for a long time. Straightforward naming conventions and Firebug can track down scoping problems really quickly.

I'm not really opposed to the changes to JS that are mentioned on the Chromium blog, but mostly because I don't have to use them. I don't really see the point of any of them -- and practically speaking, they won't see widespread use anyway until IE 9 dies out -- but maybe I'm just not imaginative enough to understand yet.


I very rarely have problems with JavaScript scoping or any of those obvious gotchas, but I still don't agree that they are good. We've just become acclimated to the language's eccentricities, the same way people living in Arizona for a long time think California summers are chilly.

It is true that JavaScript's scoping rules are pretty simple, but less is not always more. Once you have learned all the patterns and gotchas, JavaScript's scoping is quite usable. But the fact that you have to use patterns where you wouldn't in another language means JavaScript is making work for you. If JavaScript had Lispy macros or some other way of altering the language, I might be more inclined to agree that the fundamental simplicity is a good thing, but without that power, the simplicity means that when you're doing complex things, the complexity missing from the language has to be written out explicitly in your code. Right now a lot of JavaScript code is a mix of function pasta and things that should be function pasta but the coder couldn't be bothered.


Yes. "let x=1" is quite clearly syntactic sugar for "(lambda(x) { ... rest of block here ... })(1)" so while you might argue that it's unnecessary (I'd disagree, but it's a respectable argument), you can't realistically claim that it would be adding a layer of complexity. The complexity is there already: the sugar is just encapsulating in a more eyeball-friendly format


I agree that unneeded complexity is bad, but not sure I agree on all the points. "let" for example adds a keyword, but it allows you to avoid a big common cause of bugs in JS (using var in loops with closures, that capture the last value in the loop). If we could, then removing "var" and replacing it with "let" would be better - but that would be a huge change, to remove "var".

> I'm probably alone in saying this, but I hope most of this stuff never sees the light of day.

In any case, this stuff is seeing the light of day. It's been in Firefox for a while, and is now being implemented in Chrome. That means two independent implementations, which is crucial for the standards process, we can expect the other browsers to follow Firefox and Chrome on this.


    So the bit about "no more need to abuse objects as dictionaries" is a bit odd. Since most things are objects, you get the power to treat functions, types, literals, etc in interesting ways.
I think this was about performance of the underlying data structure. In this sense, a specialized collections data structure will be an "object" too.


What makes JS powerful is its simplicity.

Wrong. What makes it powerful is its ubiquity and the fact that it's de facto the only game in town for browser behavior scripting.

Want a constant? Make a global variable and don't change it.

That involved mental overhead (and team co-ordination) that makes it far less simple than "const foo".

Scope in JS is very simple to understand

Simple != intuitive or less prone to bugs. Brainfuck is also simple to understand, just a handful of rules. I wouldn't want to program in it, though...

One of the strengths of js is that every thing is an object(almost). So the bit about "no more need to abuse objects as dictionaries" is a bit odd. Since most things are objects, you get the power to treat functions, types, literals, etc in interesting ways.

Yeah, the only thing you DON'T get is an actual dictionary. Without hidden values coming from prototype, without reserved words, etc.

This proposals retains all that power PLUS gives you an actual bloody dictionary, one of the three more basic data structures in all of programming, without the toil and the million edge cases objects as dicts have.

For me, I almost never use == so it should be gotten rid of.

So what you consider as strengths are the shortcomings, and what you consider as a problem is an actual case that it can be considered a neat feature. The way js is designed, "==" makes more sense, because it lets you use more dynamic equality checking.


Wrong. What makes JavaScript popular is how good it is. You can't explain its mass popularity growth in non browser setting (node js ) with its ubiquity. It is a great language, and perhaps ubiquity was needed to get a lot of people to try out new concepts.


Have you used Javascript? I mean to do real-web apps, not to enhance some webpages with a bit of JQuery (as useful as that is).

Var is broken in js because it does not obey sensible semantics

    for(var i....
does what you think it does. In every language except javascript it would declare i only inside the loop. In js it declares i in whatever function scope the loop is inside.

    A = function(){
        console.log(this);
    }
    A.prototype.q = function(b){
        this.h = b;
    }

    imp = new A();
    setTimeout(100, imp.q)

    //later, in a response to a user event
    console.log(imp.h)
   
prints undefined. Why? because in Javascript the value of this changes. There is literally no other language where this is dynamically (as opposed to lexically) scoped.

Don't even get me started on the lack of ints, the lack of static types (which means your IDEs suck).

As for why node decieded to go with js? No idea, though it is one of the things I hate most about node. Haskell would have been a better choice, as would Lua.


> Var is broken in js because it does not obey sensible semantics

Scoping is broken in pretty much all modern dynamic languages.

Take Ruby for example:

    i = 10
    [1, 2, 3].map{|i| i * 3}
    [1, 2, 3].map{|j| j * 3}
    puts i # prints 3
    puts j # raises undefined local variable
Or let's look at Python:

    def maybe_append(b=[], n = None):
        if not n is None: b.append(n)
        return b
    print maybe_append(n=20) # prints [20]
    print maybe_append(n=30) # prints [20, 30]
So there's only a single instance of [], so that the default argument "grows" over time.


It's things like this that make me realize how right Clojure gets it (and I've been burned by python on that same "bug").


Your argument makes it pretty clear it is you that have not used Javascript very much.

setTimeout( 100, imp.q) // DOESN'T DO ANYTHING, 100 is not a function

And if you thought about it for more than a few seconds, you would realize that the behavior of "this" makes sense and is less magical than in other languages. Since "imp.q" is not a function call, it is a reference to a function, you are simply passing in a function. Since javascript "classes" are just objects with function references, you can't somehow decide what object "this" should point at unless it is explicit. In the case of "foo.bar()", it is explicitly "foo". In the case of setTimeout( foo.bar, 100), all setTimeout gets is a function pointer with no notion of what this should be.

Anyway, the rest of your gripes just sound like you don't like untyped languages, which is personal preference and I guess I don't share your preference.


I haven't used setTimeout much, but I do use js everyday (it is my fulltime job).

And it may be nice to have 'just objects with function references' when you are writting a few lines of code to validate emails or something like than. When you start pushing 2k lines of code and more than two developers you need much more structure than than that. Anyhow C++, Scala and C# all have reasonable understanding of this. If all you have are function points, don't have this.


> What makes JavaScript popular is how good it is.

If you are trying to be sarcastic, you are not doing it right.


Hah, no reason to get defensive. Javascript is a great language. If you don't like it, you are free to feel that way. But there is a huge number of people who like it. Personally, it is my favorite programming language. It just feels right.

And I've only been using it for a few years. It really isn't hard to get past the bad parts.


Wrong. What makes JavaScript popular is how good it is. You can't explain its mass popularity growth in non browser setting (node js ) with its ubiquity.

Sure you can. Node.js is not even that impressive: similar solutions exist in lots of other languages, Ruby, Python, even Java. The Node guy wrote Node in JS for two reasons: V8 was a good and fast environment, and JS didn't have much existing libraries, so people could start making new async libs.


    > No surprises, no more need to abuse objects as dictionaries.
... pretty much every single file of JS ever written is "guilty" of this.


I've only delved into really writing JS for the last couple of weeks, but a number of tutorials basically said that objects are dictionaries and vice versa, you just got some nice syntax and you can plug function in as values.

If that was an abuse, what are JavaScript objects supposed to be? What's the difference between them and a dictionary?


It's only an abuse because JavaScript has no distinction between the notion of an object's "meta" properties, and its dictionary-like keys and values. So you'll get along just fine, until someone tries to write this:

    var dict = {};

    dict["hasOwnProperty"] = true;

    dict["toString"] = "Bob";

    dict["valueOf"] = 7;
... then you're in for a rough time.


Another problem with objects-as-dictionaries is that the keys must be strings. If you use a different type as a key, it is implicitly converted to a string, which can lead to some surprising problems for programmers who don't expect it.

Maps/Set/WeakMap properly support arbitrary objects as keys.


Again, this is something that is simple to learn and understand. And you would learn this in a beginner tutorial. Why go through trouble to change it and complicate the language even further? I undeerstand weakmap may have some real advantage as far as GC, at least.


Again, this is something that is simple to learn and understand. And you would learn this in a beginner tutorial. Why go through trouble to change it and complicate the language even further?

For one simple to understand != intuitive or easy to use. Chess rules are easy to understand too, you can learn all of them in an hour, but try to play the game with any quality. So this being simple to understand does not mean its simple to code around and debug.

You are also misguided in that this addition "complicates the language". It's not like adding generics or monads or some crazy new feature. It's one of the most fundamental datatypes, implemented properly for the first time.

So, instead of saying Object foo; foo.x = "a"; when you need a dict, and having to guard against all consequences, you get to use Map foo; foo.x = "a"; and there is nothing you have to think about anymore.


Byt anyone with even a basic tutorial understanding of the language wouldn't do that. Is it really necessary to try and make it absolutely impossible to get unexpected results? The downside is even more complexity and uncertainty. Now you have to know the old way, the new way, and the idiosynchracies of both.


You might not write:

  dict["valueOf"]
since that's obviously a bad idea, but you might write:

  dict[user_provided_string]
Since user_provided_string could be anything, you are susceptible to unexpected behavior if the string ends up being "valueOf".


But even if you use an arbitrary object....if it comes from a user supplied value you are going to have to validate it somehow.

It would be great if the post included good examples of how these things are going to produce better code. Maybe my imagination or experience is just insufficient to see the great win here.


Validated or not there are still many cases where this is a valid key and thus completely breaks the object. For example, this might be a login name, most people would consider it unreasonable to not allow js keywords as logins. For a simpler example, imagine a dictionary of syntax highlighted words for js ;)

There are workarounds of course, but the ironic result is that when you want to use a js object as an actual hash/dictionary (something we are repeatedly told js is great at), your code devolves into a defensive programming mess, requiring constructions like Object.prototype.hasOwnProperty.apply, etc.


But instead if you write:

  dict[ "_" + user_provided_string ]
then nothing can ever go wrong. This does have an annoyance around the leading underscores. But you can get around that by adding simple accessor methods. And now you have a real dictionary.

But native dictionaries have the ability to store complex objects as keys. This is kind of nice. However they are likely to create traps like making these 2 different:

   my_dict[5], my_dict['5']


"then nothing can ever go wrong."

What about the key "_proto__" (forming "__proto__") [1]? That will screw up your dictionary badly.

It's not so easy. Which is why you want Harmony Maps and Sets in the first place.

[1]: https://developer.mozilla.org/en/JavaScript/Reference/Global...


Good point. I shouldn't have tossed that off of the top of my head, particularly since I'm not a JavaScript programmer. But the principle is right, you just need a different starting key than "_" to avoid conflict. Something like, "dict_" should work. And hide the details behind accessors. So if that breaks in a future version of JavaScript, it is easy to change it again.


then nothing can ever go wrong.

Yes, let's add some arbitrary personal convention you have to follow and keep track of, because it's so much easy than a proper Map type...

But you can get around that by adding simple accessor methods. And now you have a real dictionary.

You still don't have a real dictionary, keys are only strings for example. You just have another lame-ass implementation of a dict in JS that avoids some edge cases and still falls prey to others.

However they are likely to create traps like making these 2 different: my_dict[5], my_dict['5']

Those two ARE different.


Those two are different, but JavaScript does not encourage clarity about when you'll have one versus the other, thereby leading to traps for unwary beginners.


Should be able to use Type.prototype.method (e.g., Object.prototype.hasOwnProperty).


var map = Object.create(null);

..will not have any of those properties. Works only in v8 though, AFAIK.


I just tested and it looks like it works in SquirrelFish/Nitro and SpiderMonkey as well. Cool trick — I didn't know about that.

But I don't think it quite solves the problem jashkenas is talking about, which is that JavaScript automatically calls certain properties of your object behind the scenes in many situations, so you aren't completely free to use any key you want. You might be able to use a no-proto object like this as the internal datastore for a map, but by itself an object with arbitrarily assigned keys would cause a lot of problems unless you were very careful with it.


I really dislike what they're doing with modules because it's such a step back from the commonjs-inspired require() that node uses. In node, require() just returns a value. That value is usually an object but often it's just a function. Why should a module that encapsulates exactly one function return anything else but that one function?

In ES.next, you've got to use pythonesque `import y from Bar` statements which introduce a frustrating correspondence between the lexicals of your own program and the export names of the module you're trying to use which is really terrible if you're using as many modules as I typically do. I presume ES.next will invent even more specific syntax for some sort of `as` like keyword to side-step this but it seems so unnecessary when javascript already has a module system that is so very good as is exploding in popularity and use (>7000 modules now on http://search.npmjs.org/).

I understand what they're trying to do with static analysis too but you can already pretty much do that and I've done it. It's not hard at all, just ignore require() statements that don't contain strings when you walk the AST, like this: https://github.com/substack/node-detective

Inventing more syntax instead of just adopting a far better module system that has seen actual use in practical situations is such a shame and ES.next is rife with this kind of prescriptivism. It irritates me to no end and I sometimes want ES.next to die a quiet death in obscurity because of it.

http://wiki.ecmascript.org/doku.php?id=harmony:modules


You haven't considered optimization -- with closed modules, the compiler can statically know, for instance, that "Math.sin" is actually the sine function and can compile that straight down to the hardware instruction. No speculation or guards are necessary.

Additionally, your static analysis must be unsound if modules are mutable. The problem is not figuring out which module is being imported, it's figuring out whether the bindings are mutated. CommonJS cannot guarantee that modules haven't been mutated.

And yes, you can rename imports. Why is "var { foo: bar } = require('baz')" so much better than "import { foo: bar } from baz;"? They look the same to me, except that the ES6 one is better for static analysis and better for optimization.


I don't think you get it. The right way to require a module in commonjs is var baz = require('baz'). The reason its better is because I can accomplish just as much as the ridiculous ES6 modules and its simple. We don't need to add complexity if it doesn't get us anywhere. I'm not convinced that static analysis is worth it. Existing module systems work just fine without this shit.


I'll try to separate out the different issues you're raising here, and respond to each individually.

1. What if I want to have my module be a function, the way that $ in jQuery is both a function and a namespace for the rest of the functionality?

This is an important use case, and so we're going to support it in ES6 modules. You'll be able to say:

    module $ at "http://jquery.com/jquery.min.js";
    $(...)
    $.ajax(...)
2. Modules will requiring using names without the prefix.

This isn't true. As you can see in the above example, you can just use $ directly, even though it's a module. You can also say:

   import ajax from $;
but you don't have to.

3. We should just standardize the node module system.

Of course, there are many different module systems being used in JS code right now, and we could just pick one. Unfortunately, we couldn't just pick the node module system, since it's fundamentally synchronous, which is great on the server side but not in the browser.

However, we feel that we can bring real advantages to JS programmers by extending the language -- we can simplify using modules, we can make some patterns direct that currently have to be written using callbacks, we can better support encapsulation, and we can allow engines to use knowledge about modules for optimization.

3. Static analysis is doable even without a static module system.

The static analysis you describe, while useful, isn't going to tell an engine statically where it can go to lookup references to an export from a module. That means it's not useful for many of the optimizations that we want to enable. Additionally, your analysis isn't sound -- it can miss uses of `require` that are generated dynamically, for example. Again, that means that engines can't use it for optimization.

Finally, if you have comments about ES development, I strongly encourage you to make them on es-discuss, rather than on HN, where they are more likely to have an impact on the development of the language.


I'll just add that I totally I agree with samth

I'm strong user of Node.js style modules (also for client side) and I see modules as proposed for Harmony as big step forward. It's basically same concept but with dedicated syntax (well put syntax) and some extra powerful features.

I've once setup some comparison how today modules written for Node.js (like modules that are functions) will look in harmony. I didn't spot any issues. See slides 86-87 at http://www.slideshare.net/medikoo/javascript-modules-done-ri...


Since it came up on twitter, here's how you'd implement the `$` module I describe above:

    export function ajax(...) { ... };
    
    // NB: not how jQuery actually works ;)
    export this(query) { return document.find(query); };
The `export this` syntax specifies how the module instance object behaves when called as a function.


Thanks for this. I'm glad that using a single export function will at least be possible. I'm still pessimistic about the amount of syntax being introduced here.

In particular, I still really dislike the special import "local renaming" syntax since it seems so unnecessary compared to just having an import keyword that returns an object and letting the programmer extract and manipulate the relevant entries. You would still get the static analysis benefits of having static imports without all the awkward complexity of the current proposal. Wouldn't it just be the same thing to Object.freeze() the export object but without any syntax magic necessary?

Plus, overloading `module` to do loading AND defining with the `module Bar at "uri"` form seems really wrong. Why can't it JUST do defining and just let import do all the loading?


First, if you want to just use objects-as-prefixes, the way require(...) works in node today, that's easy to do:

    module m at "blah.com";
    ... references to m go here ...
We also want to support other use cases, like binding the exports to names available in your local scope. We understand that not everyone likes that style, but I don't think the language should mandate a particular side in that fight.

Second, the `module m at "URL"` form above is a definition of `m`. It's just that you're allowed to refer to that binding as an object too. Would you rather have:

    module m at "example.com";
    import m;
That just seems like unnecessary typing to me.


I mean why does `module` pull down resources? Shouldn't that be import's job?


There are two reasons:

1. `module` is about defining the modules that you're using in your program, some of which might be remote resources. `import` is about bringing names into scope.

2. Using `module` this way lets you, the client, decide on names for modules, which means we don't have to rely on module authors to come up with and use naming conventions (net.substack.airport, anyone?).

This feeds back into 1, where we use bindings to reference modules, even remote ones.

Also, if a module is never referenced or imported, then the resources shouldn't need to be pulled down at all. So partly it depends on the way you look at things.


To make my perspective here clear, I should mention that Dave Herman (of Mozilla Research) and I are the designers of the ES6 module system.


Totalyl agree. The lack of a module system in JavaScript has been an enormous benefit to the developer community, because it has allowed us to develop idioms that make sense in the context of JavaScript.

Adopting a hard-coded, python-esque module system is a step backwards from what we have now, and I doubt will be used much, if at all -- why give up features that already exist (and will continue to work)?

sigh


Sure, the top JS language designers in the ES6 group haven't thought of these issues...


Attempts to create big iterations on successful languages seem to consistently fail to win adoption.


C++ seems like a pretty obvious counterexample, even though it didn't call itself "C". Others: Fortran 90. Common Lisp. Visual Basic. [EDITED to add: Perl 5.]

ANSI C was quite a big change from K&R, even.


Not to mention: C11x (or whatever it's called), which has huge support from vendors and C++ guys, C# 4.0 that is miles ahead of C# 1.0,


+1 (and substack is talking)


    > (Caveat: Iteration over collections is not yet specified)
Is this a joke? Is not iterating over dictionaries and arrays javascript's most glaring weakness?

How hard would it be to agree on something like foreach, that, you know, actually works the way you think it should work.


There is a foreach that works: .forEach(). And when you're not just iterating over an array but transforming it, you have map(), reduce() and filter().


Is it really too much to ask to have some syntactic sugar. Is

    for i,v in blah
, where i is an index of an array, or a key (not a property!) of a dictionary really too much to ask in 2012?

No wonder people are using coffeescript.


CoffeeScript's got you covered. Here's forEach ...

    for item, index in list
... here's the same over an object ...

    for key, value of object
... here's the map() ...

    mapped = for item in list
... here's the filter() ...

    filtered = for item in list when item.isActive
... and so on.


Exactly. The number one thing javascript should take from coffeescript is the iteration syntax.


ecmascript 6 will also introduce for of loops which is said to fix for in. checkout wiki.ecmascript.org for all the ecmascript 6/harmony niceness


Remember that the spec won't come out for a while, after a pile of additional development. Also remember that we have to live with it for a long time, so taking the time to get it right seems preferable.


A different way to put it is: "the best way to iterate over collections is still being discussed, because we want to get it right".

Also, for `Map`, how do you think `foreach` should work? Should the function be called with (a) the key, (b) the value, (c) an array with both the key and the value, (d) the key and the value as separate arguments?

Similarly, in the statement:

    for(let x of some_map) { ... }
should `x` range over the keys, values, or key-value pairs of the map?


My guess would be bikeshedding.


Firefox nightlies have all of these features as well. Good to see Chrome following suit.


Minor nitpick - FF has had let scoping for a long time. WeakMap has been around since FF 6[1].

[1]: https://developer.mozilla.org/en/JavaScript/Reference/Global...


"Now "let" is the new "var" – traditional "var" declarations are complemented with "let" and "const". Both are properly block-scoped bindings, eliminating a common source of errors and weird behaviour."

Somehow going from one keyword for variable declaration to three doesn't seem like a good way to reduce errors.


JavaScript's 'var' behavior is a bug codified in specification. It is counter to pretty much any other C-style language; the difference is particularly acute because it breaks closures. So while other languages (e.g. C) could optimize their variable implementation to be like JavaScript's and still make sense, the fact that JS has closures means this breakage becomes visible on a routine basis.

However, they cannot change var's semantics and retain backwards compatibility. So they did the next best thing: introduce a new keyword for variables that work like they should. That keyword is 'let'.

As far as I am concerned, if your JS is known to execute in an environment with 'let', 'var' might as well not exist. Too many subtle errors — “what do you mean, braces don't actually delimit scope?”


If var is counter to other C-style languages, that doesn't make it a bug. It just makes it unique. Is there some other reason you're saying it is a bug? How does it break closures? Javascript works with var today and closures are used all the time. Breakage free.

"what do you mean, braces don't actually delimit scope?" I would answer, they don't. Because this is not <insert your favourite braces-delimit-scope language>. This is javascript. Nobody should have ever told you that braces delimit scope here.

It's not like this is some extremely rare issue that you aren't going to find documentation for. A quick run through a basic tutorial would suffice.

So how is it that 'let' works the way variables should? It works differently, that's all. So now you have to know how let is different from var, why it was introduced, when to use let, when to use var, etc.

Then when you see code using let, you're going to have to determine whether the person used it because they know what they are doing, or because someone just told them "let is the new var" and they use it all the time. Same for var. There is an added level of uncertainty when reading code. And and added level of complexity in explaining the language. You haven't gotten away from explaining how var works. Because you're still going to see tons of code using it.

Wouldn't it be easier to just learn how to use var properly?


It's a “bug” (and yes, I'm using that deliberately in an opinion-as-fact sense) because it is a blatant violation of the Principle of Least Surprise, especially for those coming from C-style backgrounds. If you are a C-style language (which JS is), and you do something in a non-C-style way, you should have a very good reason (besides implementation artifacts and/or not thinking robustly about scope). I haven't seen anything indicating that var's behavior is a well-reasoned, principled choice - as far as I know, it's just how JS 1.0 worked, and we're stuck with it.

In my opinion, unnecessary surprise as a result of historical implementation artifacts is a design bug.

Yep, need to learn about it. Yep, you can, and write good JavaScript. But that doesn't mean the design is good.


I don't want leg braces! Wouldn't it be easier to just learn how to use a wheelchair properly?


If var is counter to other C-style languages, that doesn't make it a bug. It just makes it unique.

Yes, it's not this that makes it a bug, it all the other horrendous stuff it entails...

Wouldn't it be easier to just learn how to use var properly?

No, it would be easier to fix it. Call it argument by authority, but I trust Brendan Eich more than some random HN dude on this.


It would be easier to just learn the language.

JavaScript I not c. JavaScript is not Java. JavaScript is not python. If it was one of those languages it would be named that and there would be no JavaScript books, just dom and browser books.

But it is not those languages. It is different. If people don't learn the language they cannot be expected to write code.

People always bring up var for some reason. Why var? Why not closures? Javascript is often the first place programmers come across this concept and it always causes confusion and bugs at first. Should we get rid of them? Of course not!


It would be easier to just learn the language.

Can you conceive the existence of a language that has got some parts wrong, and maybe awfully wrong?

Well, my point, and that of a lot of others, including Cockford and Eich, is that Javascript is such a language. And that the fucked-up scope it has, is one of such parts.

JavaScript I not c. JavaScript is not Java. JavaScript is not python. If it was one of those languages it would be named that and there would be no JavaScript books, just dom and browser books. But it is not those languages. It is different. If people don't learn the language they cannot be expected to write code.

People don't want Javascript to be Python, C, or Java. The want it to be a better Javascript and shed some of the BS that was added at its' conception due to a tight deadline. Being "different" than other languages is OK. Being brain damaged is not.

People must learn the language, but that doesn't mean they have to put up with mistakes in its' design and not correct them. Just like people corrected bad stuff in K&R C with ANSI C, Python with Python 3, Ruby with 1.9, etc.

You seem to have the wrong impression that people complaining are lazy programmers who don't want to bother to learn the language. They are not. Brendan Eich is a JS guru and implementer. Douglas Cockford invented the damn language! And he admitted that there are bad parts in it, that need to be corrected. He even made a book on how to work around those, called "Javascript, the good parts".

People always bring up var for some reason. Why var? Why not closures? Javascript is often the first place programmers come across this concept and it always causes confusion and bugs at first. Should we get rid of them? Of course not!

Because discussing what must be corrected is not about whether it's confusing to newcomers of not, it's about whether something is nicely designed OR a kludgy disaster.

Closures, while confusing to some, are a standard programming feature and a nice addition to Javascript. In contrast, var (and JS's scope rules) are just things that the JS creator gotten wrong. They need to be corrected.


"People don't want Javascript to be Python, C, or Java. The want it to be a better Javascript and shed some of the BS that was added at its' conception."

That's a great idea. I'd be all for shedding some of the bs for a better javascript. But the var issue isn't being solved by shedding anything. Var will still be there. But now the language will be even more complicated because of some var workarounds being added in. In the end, you still need to deal with var.


In the end, you still need to deal with var.

For legacy code, yes.

But now, if you target modern browsers, you can build a whole web app using only let, and not be bothered about var and the old scope system at all.


> Brendan Eich is a JS guru and implementer. Douglas Cockford invented the damn language!

Er, not quite sir. Brendan Eich invented the language. He is indeed a guru and an implementer; in fact the original implementer.

Crockford is a guru, and more importantly a pundit.


The extra keywords aren't going to reduce the "errors and weird behavior", the fact that they will be block-scoped and not function-scoped is what will eliminate the confusion.


I agree with geuis above, JavaScript scope is simple to understand now. There is global scope, and there is function scope. That's it. And there's a certain elegance to that.


There are more scopes than that: free variables versus locals; eval-introduced bindings; "with"; the exception identifier in "catch"; the function name in named function expressions; argument names; etc.

And the scoping rules are quite tricky in practice, to real programmers. To take an example from today:

https://bugs.webkit.org/show_bug.cgi?id=27226#c4


Looking at that example, I would ask ....where exactly is that function definition getting defined? Why would you put a function definition inside a catch block? Do you think it's getting defined when the catch block is called? Are you programming in Javascript, or are you just writing javascript the way you would write code in some other language?


It's a pretty straightforward use-case: you have a function that returns a function, and in the case of an internal error, you want the returned function to have a reference to the error object. And the only reliable way to do that is to declare a variable with function scope, declare a function in function scope, and conditionally return this function? That's absurdly broken.

As for variable scoping rules, if you have never been bitten by loop counters being used improperly, then I assert that you haven't programmed enough javascript. There are so many ways to mess this up: forget a var declaration and it leaks scope -- and since you can only declare it once, you can't just always use "for (var i = ...". If you want to defer access to a loop counter, then you have to remember to explicitly pass it by value to an inner closure. That last one in particular bites me all the time -- JSLint at least warns you about the first one.


It doesn't though. Because how are you ggoing to know that they operate that way? You will have to learn that somehow. And you couldve just as easily learned how var works instead.

What's worse.... now you still need to learn how var works anyway! It isn't gone. I see 0 reduction in confusion and +3 increase in cognitive load.


I understand what you're saying, but I'm under the impression that once these new keywords are introduced, everyone will encouraged to use 'let' exclusively and 'var' will be suggested as an advanced feature for special cases.


Would there be any possibility for the addition of native Long numbers to JavaScript, or is this, due to some nature of the language, something that can't, or shouldn't, be included?


I'd settle for integers. :)


You could add a 64-bit int type, sure, but since implementations use pointer-sized data that has to represent other types as well, making it as efficient as a long long in C isn't as easy. Seems unlikely to muster enough priority. (I haven't been following their work, though.)


64-bit bitwise operations would be a big help.


Anyone know where can I request a OrderedMap? That committee Wiki seems hardened against intruders.

Would be really unfortunate to have to wait for a native OrderedMap/SortedMap/TreeMap until ES7.


Bring it up on es-discuss https://mail.mozilla.org/listinfo/es-discuss

But please, search the archives first and be aware of what discussions have already taken place on this subject. =]


It is due by the end of next year

Ouch. I guess the end of 2013 is sooner than never.


> The ECMA committee is working hard on designing

"Committee" and "designing" in the same sentence gives me the shivers.

But the features they're describing actually sound pretty reasonable. Actually a lot of them seem to already exist in Lua ("proxies" sound like what are provided by Lua's metatables, and Lua already has weak tables and lexical scoping).


Lexical scoping, strict mode, hash tables. Is it just me, or did this post make JS sound a little ... Perlish?


I had been wondering when Harmony was due. The end of NEXT year? Wow, that's a long wait.


Is it really not out for 2 years? Really? That seems like a long time for not that much changes. Any improvement is welcome, but still. I don't know if this will keep pace with Dart and other options. It seems way too slow.


Really?

You seriously think Dart is anywhere close to taking over Javascript?


No I don't but my point is that 2 years seems a bit slow as far as evolution of JS is concerned.


I two years? I hope so (I use Javascript and hate it) but either way 2 years is 17 major releases of Chrome away. Much can happen before then.


The post links to an outdated Proxy spec. Here's the right link: http://wiki.ecmascript.org/doku.php?id=harmony:direct_proxie...


Also, this is a great paper posted on ES-discuss about Proxies: https://mail.mozilla.org/pipermail/es-discuss/attachments/20...


It seems Chrome actually implements the old proxy API, not the new direct proxy API.

It has the old Proxy.create() instead of Proxy.for(), which is the way to define a proxy as per direct proxy API.

So if anyone wants to implement proxies in current Chrome, they have to refer to the old proxy API (which is why they have linked to it).


Futures like in node-fibers? https://github.com/laverdet/node-fibers I think it is the proper way to complement generators and give the alternative to wait for a function value.


I don't think there's a reason to bake futures/promises into the language. Once you've got coroutines (generators here), people can build the abstractions around them that they like.


Could somebody clarify, but I feel like I won't ever use this. Older browsers won't understand these new "features", so I still will have to code as I am used to. So I guess in 20 years... I might dabble with them.


You can use this any time you know your target environment. For instance, if you write JavaScript for Firefox addons, Greasemonkey scripts, Chrome extensions, or node.js, you know exactly what JavaScript engine you'll run on, and you can take advantage of new JavaScript features that engine implements.

You can also use new JavaScript features the same way you use other new browser features like WebSocket or cross-domain xmlHttpRequest: when you've determined that all the modern browsers implement the feature you care about. The browser vendors reach a point where they stop supporting older versions with security updates and similar; I'd consider it reasonable to stop supporting a browser when it stops receiving security updates. (You should also evaluate your audience and the browsers they actually use.) At that point, older browsers get the same experience as links or wget: they get the content, but not the enhancements provided by JavaScript or whatever other features you use.


After reading many of really great comments on this post, I think that additions to a language deserve community input. Not just a couple of the "Best" programmers sitting around a table deciding.

This is the Web, after all. An interconnected world-wide community. Why isn't there some sort of voting process that anyone can give their input for ECMAScript's drafts? Right now it's an Oligarchy. At the very least, an electoral college-like system would be nice.


As long as this doesn't become another difference between browsers (= headache).


Even with optimistic estimates, it's going to be years, likely decades, before you can rely on these features being supported by the majorly of browsers. That's kind of sad but is the hard reality. I hope they come up with a good design.

I think they should be very conservative about what they propose. It should be a very obvious improvement to the language or have a lot of design time spent on it. If all major browser developers are not on board (Microsoft?) then the improvement is much less valuable.


It would be nice if there was some mechanism --at least for dynamic languages-- where when a feature X (say, the new "let" keyword) is introduced in the compiler, you can add some code that adds support for it at runtime. Maybe with some kind of name-mangling to avoid name clashes with existing variable names, etc.

Of course it would incur a performance penalty, and for some stuff it might also be infeasible, but there could be some low level package just for this purpose, that provided options to add new keywords, bytecodes, etc.

The end result would be something like (in mock-pyjs glory):

if __language__.has_not("let") import __Future__.Let".

This would enable faster iterations of the main language, while keeping backwards compatibility. Anyone knows if anything like this exists?

(Well, you can do sort of this kind of thing in Lisp. But has it ever been attempted in a C-like syntax?)

P.S My understanding is that Python does not do this, it just makes the __future__ imported modules optional in the previous version of the compiler, but they are still implemented in plain C along with the rest of CPython, no?


Personally, I'd love to see an implementation of ES.next as a static compiler. Much like CoffeeScript provides a JavaScript-like language that compiles to JavaScript, an ES.next compiler could compile ES.next JavaScript to cross-browser JavaScript.




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

Search: