28

I'm not asking what's technically possible; I know you can do

const a = [];
const b = {};
a.push['sup'];
b.test = 'earth';

What I'm wondering is whether there's any convention for preferring let over const when it comes to arrays and objects that will have their internals modified. If you see an object declared with const, do you assume the intention was for the object to be immutable, and would you have preferred to see let instead, or, since some linters (like tslint) have a problem with that, is it better just to declare it with const and trust that anyone else reading the code knows that that doesn't mean it's immutable?

redOctober13
  • 3,662
  • 6
  • 34
  • 61
  • 1
    I prefer `const` for this purpose, because the variable will always refer to the same object. But if it's your code, use whatever you prefer. If you work in a team and are worried they might get confused then write a coding standards document for the team: problem solved. – nnnnnn Mar 30 '16 at 11:04
  • 1
    Always use `const` if possible. If you really need to freeze the object, use https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze. – Ioan Aug 26 '16 at 10:22
  • 1
    You forgot `var`, still the preferred way to declare a variable that doesn't need special scoping rules or immutable behaviour – adeneo Oct 03 '17 at 20:41
  • 6
    @adeneo I disagree. I never use `var` anymore. There's really no reason to. As for which to use, `let` or `const`, that's all up to opinion. If I intend for something to not be touched, I use `const`. If it *really* shouldn't be touched, and it's some kind of object, I use [`Object.freeze`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze). – Mike Cluck Oct 03 '17 at 20:43
  • IMO, there’s no reason not to declare arrays and objects with `const`, since you’re most likely not going to redefine `a` and `b`. _I personally_ know that it doesn’t mean that they are immutable; for immutability I would use e.g. `Object.freeze`, but someone else might misinterpret that… – Sebastian Simon Oct 03 '17 at 20:43
  • As the comments already show, there is no best-practice convention on this. It is a matter of preference. As such, I'm voting to close this question as it is primarily opinion based. – Scott Marcus Oct 03 '17 at 20:45
  • 1
    @MikeC - I use `var` all the time, and only use the other two when they make things easier. If you never find a reason to use variables that aren't block scoped, that's up to you, I do. – adeneo Oct 03 '17 at 20:48
  • @adeneo `var` just uses function scoping rather than block scoping. If I intend to use a variable through a function then I declare it at the function scope with `let` or `const`. Declaring variables in child blocks which are then used in parent or siblings blocks is confusing and uncomfortable in my opinion. – Mike Cluck Oct 03 '17 at 20:49
  • 2
    Come up with your own convention (and write it down) and stick to it. Consistency is the most important here. – Bergi Oct 03 '17 at 20:51
  • Related: http://programmers.stackexchange.com/questions/278652/how-much-should-i-be-using-let-vs-const-in-es6, https://stackoverflow.com/questions/44604212/when-to-use-const-with-objects-in-javascript, https://stackoverflow.com/questions/10843572/how-to-create-javascript-constants-as-properties-of-objects-using-const-keyword – Cody Gray - on strike Apr 21 '22 at 06:16

4 Answers4

40

The const keyword in front of an object implies that there is an object, and you're working with references to alter it. It also (correctly) implies that you should not attempt to reassign references to this object.

const obj = {a: 'foo', b: 'bar'};

const obj2 = {z: 'baz'};

obj = obj2; // const will prevent this operation. 

const does not imply that the object properties should not be altered. It does imply that you should not try to change the reference.

If you plan to reassign references to the object, then you use let.

Source: AirBnB Javascript Style Guide

LennieCodes
  • 733
  • 8
  • 13
18

I favor const over let in ES6. In JavaScript, const means that the identifier can’t be reassigned. (Not to be confused with immutable values. Unlike true immutable datatypes such as those produced by Immutable.js and Mori, a const object can have properties mutated.)

If I don’t need to reassign, const is my default choice over let because I want the usage to be as clear as possible in the code.

I use let when I need to reassign a variable. Because I use one variable to represent one thing, the use case for let tends to be for loops or mathematical algorithms.

Reference: https://medium.com/javascript-scene/javascript-es6-var-let-or-const-ba58b8dcde75#.9s2e58ihw

Example from MDN: The const declaration creates a read-only reference to a value. It does not mean the value it holds is immutable, just that the variable identifier cannot be reassigned.

const name1 = value1 [, name2 = value2 [, ... [, nameN = valueN]]];

nameN The constant's name, which can be any legal identifier. valueN The constant's value; this can be any legal expression.

The let statement declares a block scope local variable, optionally initializing it to a value.

let var1 [= value1] [, var2 [= value2]] [, ..., varN [= valueN]];

var1, var2, …, varN Variable name. It can be any legal identifier. value1, value2, …, valueN Initial value of the variable. It can be any legal expression.

From my opinion, it fairly depends on what you want to do with them. I found the statements above convincing enough to share with you.

9

There is no preferred one, its based on your choice of usage for that array or object. You have to understand mutation and reassigning clearly.

Mutation - updates the values present in the memory

Reassign - variable points to new memory locations where new values are stored

Let - offers both mutation and reassiging

Const - offers mutation but not reassiging

Both - doesnot offers redeclaring

If your usecase only needs mutation, you can go for const.. if you need reassigning then go for let.

// LET

let condiments = ['Ketchup', 'Soy Sauce', 'Sriracha'];

// Mutation possible
condiments[0] = 'Mayo';
console.log(condiments);//=> [ 'Mayo', 'Soy Sauce', 'Sriracha' ]

// Re-assigning possible
condiments = ['Mayo'];
console.log(condiments); //=> [ 'Mayo' ]

// Re-declaring not possible
//let condiments = [] //=> SyntaxError: Identifier 'condiments' has already been declared


// CONST

const utensils = ['Fork', 'Chopsticks', 'Spork'];

// Mutation Possible
utensils[2] = 'Spoon'
console.log(utensils); //=> [ 'Fork', 'Chopsticks', 'Spoon' ]
utensils.length = 0
console.log(utensils); //=> [ ]

// Re-assigning not possible
//utensils = ['Spoon']; //=> TypeError: Assignment to constant variable.

// Re-declaring not possible
//const utensils = {} //=> SyntaxError: Identifier 'condiments' has already been declared
3

This is probably a question you wont be able to get a final answer for, as it is very opinion-based.

A little bit of historical background can help to understand how the confusing const came to be in the first place:

Allan Wirfs-Brock, the former editor of the EcmaScript spec, himself said:

In a slightly different (and perhaps better) universe, ECMAScript const declaration would be named let and introduce a SSA binding.

And asked, why this was not the case, he responded:

let/const was a carry over from ES4 proposals and Moz JS1.7

TC39 never seriously explored naming alternatives

So you could say const is a bit of a misnomer, since it doesn't do what people who aren't familiar with it might expect it to do.

Since const works the way it does though and is almost certainly not going to change, I would still define your objects with const.

This might help people who are unfamiliar with the way const works to get a better understanding.

Maybe it could help to add a comment at the first occurrence of const with an object, along the lines of:

// Important: 'const' only ensures that 'styles' always references the same object,
// it does not render it immutable
const styles = {};

Opinions may vary though.

nils
  • 25,734
  • 5
  • 70
  • 79