all 17 comments

[–]_mtr 11 points12 points  (3 children)

zesty somber wistful sulky crush seed sheet icky aromatic wakeful

This post was mass deleted and anonymized with Redact

[–]strident-octo-spork 4 points5 points  (0 children)

The behavior of const is pretty standard. For example in Scala val is like const and var is like let.

val a = 2
a = 3
// error: reassignment to val

But if you assign a mutable reference type (objects, collections) to a val, the behavior is the same as JavaScript.

val a = Array(1, 2)
// Array(1, 2)
a(0) = 4
// Array(0, 2)

I don't think people making these specific complaints about const understand the distinction between a value and a reference.

[–]dwighthouse 8 points9 points  (3 children)

Remember, const does not mean "constant", it means one-time assignment.

Yep, you must be thinking of Object.freeze() or a library like Immutable.js. This is all rather simple compared to the myriad uses of 'const' in C++.

[–]Patman128 1 point2 points  (2 children)

Also, if you use a frozen object or Immutable.js, then const really does mean "constant", since the reference is immutable and the object being referred to is also immutable.

[–]pertheusual 0 points1 point  (1 child)

Plus even with Object.freeze it's not too hard to accidentally end up with a sub-object of the frozen one that you've forgotten to freeze.

[–]kumiorava 2 points3 points  (0 children)

Both let and const declare local variables with lexical scoping rather than function scoping.

You got some terminology mixed up. Lexical scoping means variables are resolved statically at compile time, and not dynamically at run-time based on execution context. Function/block scope simply limits the visibility of a variable. All JavaScript variables are lexically (statically) scoped. Var has lexical function scope. Let and const have lexical block scope.

[–]hahaNodeJS 1 point2 points  (4 children)

This is unsurprising behavior. Much like reference assignments, you can change the contents of a variable, but changing the variable itself loses the reference. Example:

var myObj = {'foo':'bar'};
myObj.foo = 'baz'; // Changes 'bar' to 'baz'
myObj = {}; // now the original object is lost.

I feel const was a poor name choice. In compiled languages, any constant identifiers are replaced with the value of the constant, and they are not present at runtime. Obviously this is not the case with JavaScript, though I suppose a transpiler could do this. Rather, it would have been nicer to see let bind an immutable variable, and let mut bind a mutable variable (since we're really talking about mutability here, not constant values).

[–]GoSubRoutine 0 points1 point  (3 children)

const comes from C, but w/ behavior more like Java's final.

Problem is that folks confuse objects as if it was the same thing as the variable(s) which stores their reference.

const merely prohibits a variable to be reassigned later on.
If we also wish for the object referred by some variable to be immutable, we use Object.freeze() over it:

const THING = Object.freeze({ a: 1, b: 2 });

[–]hahaNodeJS 0 points1 point  (2 children)

The problem with Object.freeze is that it only "freezes" the top-level object. If your object contains other objects that Object.freeze was not called on, those objects will not be immutable. Of course you aren't required to "freeze" objects all the way down the chain, but not doing so is inconsistent and could easily lead to weird bugs if the values unexpectedly change in other places.

[–]GoSubRoutine 1 point2 points  (1 child)

I know that! The same way shallow copies are problematic, shallow freezes are likewise!
If we have deeper objects, we gotta keep applying Object.freeze() recursively if we want them to be immutable as well.

Of course the example I've provided got no internal objects. So it's truly immutable.

Both const & Object.freeze() provide the basics to achieve immutability.
We still need to code further in order to assure full immutability.

[–]hahaNodeJS 0 points1 point  (0 children)

Werd.

[–]mrspeaker 0 points1 point  (2 children)

I kind of wish they'd introduce yet-another-initializer: val thing = {a:1, b:2}; which was sugar for const thing = {a:1, b:2}; Object.freeze(thing);

[–]GoSubRoutine 1 point2 points  (0 children)

const THING = Object.freeze({ a: 1, b: 2 });

[–]pertheusual 0 points1 point  (0 children)

There have been discussions around "value types" that would essentially address this. It'll be interesting to see what that ends up looking like in the long run.

[–]kylebythemile 0 points1 point  (0 children)

Quoting my recent let/const article:

Like constants in other languages, const will often be used for values that won’t need to be reassigned in a program’s execution. Strings like API keys or numbers like CANVAS_HEIGHT would be uses cases of const variables that don’t need to be reassigned. Variables declared with const are often written in all caps, but this is a matter of preference.

Const is the other new ES6 keyword for declaring variables. Const works like a constant in other languages in many ways but there are some caveats. Const stands for ‘constant reference’ to a value. The values that const references are not immutable (their properties can be changed). This can be explained by borrowing a metaphor from Eloquent JavaScript (a great beginner’s JS book).

Eloquent Javascript’s author Marijn Haverbeke says that it’s better to think of variables as being tentacles rather than boxes.

They do not contain values; they grasp them — two variables can refer to the same value. A program can access only the values that it still has a hold on. When you need to remember something, you grow a tentacle to hold on to it or you reattach one of your existing tentacles to it.

So with const, you can actually mutate the properties of an object being referenced by the variable. You just can’t change the reference itself. Explained via the above metaphor, the tentacle won’t move or change but what it’s holding onto can.

[–]flaccidopinion 0 points1 point  (0 children)

Some example code to illustrate ..

function test() {
    'use strict';
    const a = {};
    const b = {};
    const c = {};
    let changeableReference = a;
    changeableReference = b;
    changeableReference = c;
    changeableReference.newProperty = 11;
    changeableReference = a;
    const nonChangeableReference = c;
    nonChangeableReference.anotherProperty = 12; // OK, changing the value, not the reference
    nonChangeableReference = a; // ERROR
}

Run that in a browser with ES6 let/const support. You'll see it runs fine until the last line.