49

As io.js now supports ES6 you are finally able to use the const and let keywords. Obviously, let is the successor of var, just with some super-powers.

But what about const? I know, of course, what "constant" means, but I was wondering when to use it (regarding best practices).

E.g., if I create a module that requires another module, I could write:

'use strict';

const util = require('util');

const foo = function () {
  // Do something with util
};

module.exports = foo;

Basically I've replaced every occurence of var with const. Generally speaking, I think that this is okay, but if I follow this pattern, it leaves me with way more uses of const than let, as most variables aren't "variables" in a literal sense.

Is this good style? Should I rather go for let? When should I choose const over let?

Golo Roden
  • 140,679
  • 96
  • 298
  • 425
  • 1
    I would expect `const` to be all in caps, like `const KEY_A = 65` for example. – elclanrs Jan 25 '15 at 10:47
  • 2
    The way I think about it, is that a `const` should be used if the value is to never be changed, or more importantly protected from change. `let` should be used when the value is to be overwritten/changed later, and both should be used when you need a block scoped variable, and not a variable scoped to a function. If you need a function scoped variable, `var` is still available. I could be wrong, haven't really read up on ES6/2015 that much. – adeneo Jan 25 '15 at 11:01
  • 2
    Declaring `util` as a `const` just means that that variable cannot be set to a different value. **However**, you are still able to add, modify, and remove properties from it if it isn't a primitive. – idbehold Jan 25 '15 at 17:07
  • also http://stackoverflow.com/questions/27565056/es6-template-literals-vs-concatenated-strings – Naeem Shaikh Jan 27 '15 at 08:38
  • 2
    Const seems to have bad performance though http://jsperf.com/const-vs-var-mod-3 – Deepu Mar 30 '16 at 07:31

5 Answers5

42

const can be normally used when you don't want your program

  1. to assign anything to the variable

    "use strict";
    const a = 1;
    a = 2;
    

    will produce TypeError: Assignment to constant variable..

  2. to use the variable without explicitly initializing.

    "use strict";
    const a;
    

    will produce SyntaxError: Unexpected token ;

Simply put, I would say,

  • use const whenever you want some variables not to be modified

  • use let if you want the exact opposite of const

  • use var, if you want to be compatible with ES5 implementations or if you want module/function level scope.

Use let only when you need block level scoping, otherwise using let or var would not make any difference.

thefourtheye
  • 233,700
  • 52
  • 457
  • 497
  • 3
    Actually, `let` and `const` do hoist, but it is a bit more complicated than that: http://stackoverflow.com/q/31219420/3242070 – Luboš Turek Jul 06 '15 at 09:43
  • I don't think the first half of this is correct. The example with `A_CONST` actually does throw an error. `const` and `let` both hoist, but are subject to the ["temporal dead zone"](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let#Temporal_dead_zone_and_errors_with_let) so they cannot be used prior to declaration. – ZachB Jun 06 '16 at 21:46
  • 1
    @ZachB I agree. In my defense, `const` used to behave differently in sloppy mode. [Ref](https://github.com/nodejs/node/pull/3152#discussion_r41552676). Thanks for pointing out, I removed the part which is wrong. – thefourtheye Jun 07 '16 at 04:51
8

I have the same feeling that you're describing. A big percentage of declared variables in my code tend to be constant, even objects and arrays. You can declare constant objects and arrays and still be able to modify them:

const arr = [];
arr.push(1);
arr;
// [ 1 ]

const obj = {};
obj.a = 1;
obj;
// { a: 1 }

AFAIK ES6 modules do not require variable declarations when importing, and I suspect that io.js will move to ES6 modules in a near future.

I think this is a personal choice. I'd always use const when requiring modules and for module local variables (foo in your example). For the rest of variables, use const appropriately, but never go mad and use const everywhere. I don't know the performance between let and const so I cannot tell if it's better to use const whenever possible.

Gabriel Llamas
  • 18,244
  • 26
  • 87
  • 112
  • 1
    Why not go mad and use `const` everywhere? I've found that I very seldom actually need a `let` (mostly when I determine a value in an `if` or `switch` clause) . There is no downside to use `const` wherever it is possible and the upside of more information about the variable for the reader. – Perseids Mar 09 '16 at 21:09
  • 1
    @Perseids I originally agreed with you, but [this article](https://medium.com/@PepsRyuu/use-let-by-default-not-const-58773e53db52) points out that using `const` everywhere nullifies the implied significance of `const` - that is, that you don't *intend* to modify it even though you could. I like the idea of using `const` to mean, "not only can I not perform a reassignment, I also don't intend to modify this object at all." – rinogo Oct 21 '20 at 19:20
  • 1
    @rinogo: The author of the article you reference and I appear to have very different work environments and working style. A SO comment is too short to discuss in detail, but broadly, I think in const values by default all the time and reassigning a variable or changing the contents of a data structure is the noteworthy outlier for me (in local function contexts). Conversely, my work environment is not homogeneous enough in coding style that I can trust coworkers to follow the convention that `const` means "don't mutate!". But if their advice works works for you, by all means, follow it. – Perseids Oct 26 '20 at 08:33
4

Performance test const vs let usage on require for Node.js 6.10:

require('do-you-even-bench')([
  { name: 'test 1', fn: function() { 
    const path = require('path');
    } 
  },
  { name: 'test 2', fn: function() { 
    let path = require('path');
    } 
  }
]);

test 1 .... 2,547,746.72 op/s
test 2 .... 2,570,044.33 op/s

rgwozdz
  • 1,093
  • 2
  • 13
  • 26
3

Background:

let is a successor of var keyword with imposed restrictions. These restrictions make the chances of making fewer mistakes and with added security. Basically, it has block scope i.e. it is only available to the block where it is declared. In other words, variables cannot be accessed outside the block it has been declared.

const accessibility is also inside block scope. But once initialized cannot be re-initialized. This can be tricky in the case of Array, Objects

What does array initialization mean?

let arr = [1, 2, 3, 4, 5];

arr contains the reference (address or pointer) of the first element of the array. That is the reason why this never holds good.

let arr1 = [1, 2, 3, 4, 5];
let arr2 = [1, 2, 3, 4, 5];
 
if (arr1 == arr2)
    console.log("Both arr1 and arr2 are same");

This shall never print Both arr1 and arr2 are same in the console. Though they looks same in all aspects. But if we see then arr1 and arr2 are pointing to different locations in the memory. The same concept goes with objects. For example:

let obj1 = {name:'John', age:'22'}
let obj2 = {name:'John', age:'22'}

if (obj1 == obj2)
     console.log("Both obj1 and obj2 are same");

obj1 and obj2 are pointing to different memory locations. So the console.log statement shall never run.

If we use const declaration for the array or object, then according to the definition it cannot be re-initialized. But actually the identifier assigned to the array or object is a memory pointer (address). The array or object can be modified (mutated) accordingly.

Answer to the question:

const util = require('util')

This type of declaration makes sure that accidentally util is not declared the second time. This makes the code less error-prone i.e. reduce the chances of making mistakes. const declaration in function makes it less error-prone. As redeclaring, it throws an error.

For instance, say there is a function you declared factorial that is responsible for finding factorial of a number. Let us consider this example:

const factorial = (n) => {
     let fact = 1;
     for(let i=1;i<=n;i++)
         fact *= i;
     return fact;
}

const factorial = 5;
console.log(factorial(10));

Here it will throw an error. const makes the use of the identifier factorial unique. i.e. a function that takes an input and finds factorial of it.

This helps in making lesser mistakes that are very difficult to debug.

If an array or object is declared const, then the array or object can be modified (mutated) but any other identifier cannot use the same name that is declared using const.

I hope this helps.

mohitesh07
  • 31
  • 1
  • 3
0

const: scope: block. reassign: not allow. declaration+initialization: must

let: scope: block. reassign:allow. declaration+initialization:optional

var: scope: global & functional. reassign: allow. declaration+initialization:optional.

According to w3schools use always use const is a good practice.

https://www.w3schools.com/js/js_const.asp

So my preference:

  1. const
  2. let
  3. var
SaimumIslam27
  • 971
  • 1
  • 8
  • 14