Hacker News new | ask | show | jobs
by tnzm 1755 days ago
So, this, but with more steps?

    function Foo () {
      var x = 1 // "static initialization block"
      return {
        y: 2,
        z: function () { return x + y }
      }
    }
    const foo = Foo()
There's been exactly zero need for the "class" keyword, "constructor()", or that new "#private" thing.

There is one flaw in the design of the language which opens the door to all this nonsense; that's having to write "foo.method.bind(foo)" instead of just "foo.method" when passing "method" as a callback, in order to preserve the value of "this". Although in the example above this is not a problem, as you can write functional code that passes the context explicitly without needing "this".

Another thing I wish JavaScript had kept was the "with" statement.

3 comments

> Another thing I wish JavaScript had kept was the "with" statement.

Consider the following:

    with (a) {
        with (b) {
            with (c) {
                d = e;
            } 
        }
    }
Does this mean:

(1) a.b.c.d = e

(2) d = a.b.c.e

(3) something else

(4) it's impossible to tell?

Correct answer: (4) it's impossible to tell!

One of the worst things about programming is looking at someone else's code (or worse, one's own code) and thinking "WTF did they mean by that?". And that's why I don't like the with statement.

a.b.c.d = a.b.c.e
or a.c.d = b.e, or a million and one other things
> that new "#private" thing

I can agree that classes have been more or less a syntactic sugar, but private identifiers are not. The field name collision is a problem in virtually every dynamically typed language with namespace inheritance and each language has their solutions (see Python `__mangled_name` and Ruby `@instance_var`), JavaScript just happens to have another solution and that alone justifies a separate `class` syntax (since the scope of such private identifiers should be lexical).

I know they're not, that's why I'm objecting to them in principle (even though I use them and they're quite handy). JavaScript already has a solution - just put the private fields in the parent closure where they can't be accessed externally. In my example above, x is a private field, and the constructor function Foo can be asynchronous. The new semantics is a kludge around the supposedly "optional" class syntax sugar.

Remember, once upon a time JS was supposed to be Scheme...

> just put the private fields in the parent closure where they can't be accessed externally

Your approach can't translate the following code:

    class MyNumber {
        #value;
        constructor(value) { this.#value = value; }
        add(other) { return new MyNumber(this.#value + other.#value); }
    }
The proper solution is to use a non-enumerable property with an unnamed Symbol name, which is possible but cumbersome.
You're not supposed to be able to refer to other.#value, though, isn't that the entire point of a private field?
They are private to classes, not instances. Many languages with private fields do allow access to private fields in other instances of the same class.
Arrow functions replace the need to use `bind` and you can still use `with` just not in strict mode unfortunately.