Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

I don't understand why you can't just use temporary variables. The article mentions mutation is bad, but what actually happens is that the name gets reassigned. No value is mutated.

That brings me to something I really want in JS, actual unmutable values. If you use `const x = new SomeClass()`, you cannot reassign it, but you can change fields. The first time I encountered `const`, I thought it did the opposite. It would be cool if you could declare something (object, array) to be an immutable value.

If you really want to introduce new operators, how about operator overloading? For example vector and matrix calculations become a lot clearer and less error-prone with infix operators. It should be technically easy to add them to typescript - rewrite the expression to a function call depending on the types of the operands - but the TS devs refuse to implement this on philosophical grounds unless it is implemented in JS. I guess in JS it would require runtime dispatch, but maybe that is not such a big penalty given that it usually uses a JIT anyway.

Oh, and while we are at it, fix `with`. The JS with statement is ridiculous and deprecated anyway. It makes all fields of an object available in it's scope. Contrast with VB6's `with`, which requires you to use a leading dot and is much more readable:

    with (elem.style) {
        .fontFamily = 'Arial';
        .color = 'red';
        console.log(.borderWidth);
        // in actual JS this would just be
        // console.log(borderWidth);
    }


A problem is that you can only declare intermediate constants in a statement context, not an expression context. And with React, more and more JS devs are spending time in expression contexts

Example:

  return (
    <div>
      {foo(bar(stuff))}
    </div>
  )
There's no way to break out inline intermediate constants here; you have to bail out and do it up above the `return`. In this case that may not be too bad, but when you've got a hundred lines of JSX, things start getting really spread out


But that's a symptom of issues with React, not issues with JavaScript.

React's declarative model makes it easy to write unreadable spaghetti React declarations that are nested ten levels deep. Nobody should be adding features to JavaScript to encourage that.

("Please, I'm begging you, for the love of sanity... Refactor into more than one component. Just one time. Look, functional components even make that cheap and easy now. Please please please, just take some of that nesting and put it in a new component.")


Highly disagree on two counts:

> that's a symptom of issues with React, not issues with JavaScript

IMO keeping as much as possible in an expression-context is preferable, even without React, because it simplifies control-flow and avoids mutation. The main problem in this case, as I see it, is that javascript doesn't fully support that style- it could and should have a feature that allows intermediate constants (but not variables!) inside expressions. (It should also have something better than ternaries for expressive conditionals, but that's a separate topic)

> Refactor into more than one component

Plenty of ink has been spilled here in the past about splitting functions when there's a real conceptual boundary, not just when they "get too large", and how otherwise keeping your code together in one place can actually make it easier to follow because you don't have to jump around all over the place. So I don't really want to get into all that again here, but suffice to say that's my stance on the subject.


I mean, we could refrain from talking about the need to "jump around," but that's the crux of the issue: modern IDEs (like vscode) include "peek" functionality to look at a definition inline. No need to jump around at all. And a thousand-line component has a thousand lines of context it could be pulling in; reasoning about that level of complexity rapidly gets complicated.

If you have some complicated expression to say inline in a React declaration, pull it up to the preparatory layer. If there are performance reasons not to do that, push it down into a subcomponent.


Technically, you should be able to write something uniquely terrible like this ;)

  return (
    <div>
      {(() => {
        const barStuff = bar(stuff);
        return foo(barStuff);
  })()}
    </div>
  )


Yeah, JS programmers sometimes work around this and similar language gaps by making an inline function and immediately calling it (because that gives you a statement context inside of an expression context, which isn't normally possible). But IMO it's very rarely worth the hit you take to readability


They should repurpose `do` so that `do {}` (without the `while`) is an expression that you can put statements inside and return the last statement.

It would be great if we had expression if..else too (instead of just the tertiary operator)


> They should repurpose `do` so that `do {}` (without the `while`) is an expression that you can put statements inside and return the last statement.

There's a proposal for precisely that. Unfortunately, only Stage 1 though.

https://github.com/tc39/proposal-do-expressions


> There's no way to break out inline intermediate constants here; you have to bail out and do it up above the `return`.

Which seems fine. There's not an obvious gain to having one giant super-complex return statement.


But isn't then the problem that JS doesn't offer more expressive function contexts? Some languages like Nim allow you to use blocks in place of expressions; the last expression in the block determines the return value. You can also use `if` as an expression. No need to introduce a separate syntax for this case. (Although I do like piping in bash, but I don't think it is a good idea for JS.)

Also sometimes you should just give stuff a temporary name, and treat React like a templating language.


The way to fix that then would be to introduce a way to create named values within an expression. E.g. have something like

  let foo = bar in <expression>
be an expression.


> That brings me to something I really want in JS, actual unmutable values. If you use `const x = new SomeClass()`, you cannot reassign it, but you can change fields. The first time I encountered `const`, I thought it did the opposite. It would be cool if you could declare something (object, array) to be an immutable value.

That sounds like a fundamental mis-understanding. Variables do not hold objects, they hold references to objects.

    const foo = {};
    let bar = foo;
foo and bar hold references to the same object. They do not hold the object themselves. foo's reference can not be changed. It's const. bar's reference can. But the object is independent of both variables.

If you want the object itself to be unmodifiable there's Object.freeze.

    const foo ...
makes foo const. If you wanted a shortcut for making the object constant (vs Object.freeze) it would be something like

    let foo = new const SomeObject()
This doesn't exist but it makes more sense than believing that `const foo` some how makes the object constant. It only makes foo constant (the reference).


I don't want to freeze the object, I want to have a handle that doesn't allow me to modify the object. (Whether that would be at all possible in JS is another question.)

So

    let foo = {field:1};
    immutable let bar = foo;
    bar.field = 2; // error
    foo.field = 3; // ok
This is what I actually want when I think "const". I don't really care that you can reuse a variable, or re-seat a value. What I care about is that I recieve an object and sometimes want to modify it, and sometimes I want to make sure it stays the same. Maybe somebody else holds a reference and I don't want to surprise them.

(The inverse problem is when I have a function that takes something like a string or a number, and I want to change that from within the function. There is no way to pass a value type by reference. You have to encapsulate the value in an object and pass that. It would be cool if you could say something like `function double(ref x) { &x = x*2; }`.)


I agree that having a "can't modify this object" via this reference is useful and that JavaScript doesn't have it. TypeScript has it with `ReadOnly<T>`

It could be worse. You could be in python that has no const whatsoever :P

I also agree pass by reference is useful. JavaScript only has pass by value, similar to python.


If you are using TypeCript checkout ReadOnly<T> utility type

https://www.typescriptlang.org/docs/handbook/utility-types.h...


I think what you're looking for is:

  const x = Object.freeze(new SomeClass())




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

Search: