7

Given something like this:

const audio = React.findDOMNode(this.refs.audio);
const seeker = React.findDOMNode(this.refs.seeker);
const {left, right} = seeker.getBoundingClientRect();
const seekToPerc = (event.clientX - left) / (right - left);

audio.currentTime = this.props.totalRunTime * seekToPerc;

Is this overusing const? Should I be using let here?

Yves M.
  • 29,855
  • 23
  • 108
  • 144
ffxsam
  • 26,428
  • 32
  • 94
  • 144
  • 2
    [No. No.](http://programmers.stackexchange.com/a/278653/66652) – Bergi Oct 23 '15 at 07:02
  • One of the worst things that can happen to a programmer is when something changes he considers constant. This can lead to bugs which are very hard to find. So put `const` on anything that is designed to be constant. – Marged Oct 23 '15 at 07:16
  • [There are those who think](http://blog.getify.com/constantly-confusing-const/) `const` is overused in ES6. I personally am not in that camp - if you're not going to reassign those variables, I would keep them `const` – CodingIntrigue Oct 23 '15 at 08:49
  • possible duplicate of http://stackoverflow.com/questions/21237105/const-in-javascript-when-to-use-it-and-is-it-necessary – Bergi Oct 31 '15 at 19:55

3 Answers3

11

The use of const is up to the individual. Optimization of most javascript engines work best if you pretend that javascript is strongly typed. const would thus seem like a good idea.

Some facts.

  • MDN states that consts are block scoped like let. This is only true in strict mode.
  • Consts must be assigned a value on declaration. Only true in strict mode.
  • Consts can not be reassigned. This is true in both strict and normal but in normal javascript assigning to a constant fails silently which represents a source of hard to find bugs. (NOTE there is no good argument for not using strict mode)

The differences as an example

function log(d){console.log(d);}
(function (){
    if(true){
        const a = 10;  // correctly formed use of constant
        const b;       // does not fail
        log(a);        // 10;
        log(b);        // undefined
        b = 10;        // nothing happens. If you have forgoten this is a constant
                       // you will have a hard time knowing this assignment is failing
        log(b);        // undefined
    }
    // scope not respected
    log(a); // 10 const should have block scope. This does not seem to be true
            // in normal javascript
})();

// function in strict mode
// not this is an example only and can not run. It is a compilation of several functions
(function (){
    "use strict";
    if(true){
        const a = 10;    
        const b;     // SyntaxError: Unexpected token. Javascript parsing 
                     // stops here and the function will never be called
        a = 20;      // TypeError: Assignment to constant variable
    }
    // scope is respected
    log(a); // ReferenceError: a is not defined
})();

As you can see there is a big difference between using const in strict mode and not. It would be foolhardy to use constants in anything but strict mode.

Performance. Chrome was very early in its adoption of const, I have memory of using const at least 3 years ago. As I specialize in graphics, performance is critical. I reasoned that a const would provide a much needed performance advantage, much the same way #define does in C/C++ by simple code insertion of the constant value. Saddly by the end of that day I was completely turned against the use of const because of it terrible performance.

Since then it has improved.

jsperf "Consts V Vars"

Using const is consistently slower in all tests but it is marginal and too close to call. The only exception being block scope declaration where it was about 1/3rd the speed of var and let. One surprising finding is that let is now very fast on Chrome Beta, a month ago I would not go near it, this fact is the reason for my answer.

OP asked... Does it make sense to use const for all variables that will never be changed?

A year ago I would have said "NEVER USE IT". A few months ago I would have said, "Have a good reason but var is better".

Now my answer is most definitely use constants whenever you intend a variable to never change. Constants out performs literals and are as good as var.

const c = 10;
var v = 10;
var a = 10; // this is slower 
var a = c; // this is 20% faster
var a = v; // this is about < 1% faster than const.

At the rate of change browsers undergo, and from the performance changes in the last few months of both let and conston chrome. I would suspect that constants will out perform vars by the end of the year. (please note I am using Chrome Beta 47)

The tests I have performed do not provide much room for code optimisation, so I would guess there is additional performance in using const that is not evident in the tests.

A constant by its very nature is strongly typed, this gives the javascript optimisation algorithms something to use to provide additional performance.

Using constants makes for better code quality. Javascript (even strict mode) can hide a bug for a long time, using constants reduces the risk of bad assignments, accidental type conversion, and more.

BUT I place a big warning on the use of const. ONLY USE const in strict mode, its behaviour in normal javascript is dangerous and will only cause you problems.

Blindman67
  • 51,134
  • 11
  • 73
  • 136
  • Wow, thanks for this! One of the best answers I've ever received on SO. :) – ffxsam Oct 31 '15 at 21:47
  • I'd loved to read "*Using constants makes for better code quality*" in the first line :-) – Bergi Oct 31 '15 at 21:59
  • I can not do that @Bergi The use of `const` without `"use strict"` is to risky. I would prefer that people read all answers and understand rather than just the headline. – Blindman67 Oct 31 '15 at 22:03
  • Sure, though I'd expect people who care for code quality to already be using strict mode anyway :-). And I still feel this answer could use a tl;dr - while your anecdotes about performance are interesting, they don't really answer the main question. – Bergi Oct 31 '15 at 22:08
  • There is not definite answer. Let or const. I favour constants, my primary focus is performance. If the OP is coding for him self then it is his personal preference. If he is part of a team then there should be a style guide and code convention documents that should be followed. If its for public consumption then there are too many copies of IE out there to use any of the ES6 features for the time being. – Blindman67 Oct 31 '15 at 22:36
  • Just a correction: `const` is block scoped in ES6, period, even when not in strict mode. – ffxsam Nov 01 '15 at 08:07
  • I just double checked my code, no mistake on my part. On Chrome 47 Beta `const` is quite evidently not respecting the standard. I was expecting the console to show `undefined` but out comes `10` and clearly `a` is outside its defined scope and holding its assigned value. Copy the first anonymous function from my answer and try it yourself. – Blindman67 Nov 01 '15 at 09:01
3

Blindman67 gives a good argument from a performance viewpoint. Since javascript/ecmascript compilers are changing/improving all the time, I would consider answering this question more from the perspective of what gives more readable/maintainable code.

Marking a variable 'const' can be useful at times, signifying that a value is immutable. This stands also for the case when the compiler would not enforce const check - like marking an object array const would still allow you to alter state of an object in that array. This of course boils down to coding style within the team, but I found most people go out on that a variable defined const, even if could be changed, is meant to be immutable.

The other hand of this argument is overusing const. Of course you can use const everywhere, it just makes the code somewhat harder to wade through, and harder to make changes to it. I've found that in practice, most maintenance work of such code begins with removing most of the 'const' keywords, so that the necessary extra changes could be done. So while having lots of constants might look like great code at first, in the longer run I think it adds close to nothing to maintainability, on the contrary, it makes maintenance harder.

tl;dr Use const where you think it adds to the readability of your code.

Agoston Horvath
  • 781
  • 8
  • 13
  • I feel that javascript does not have a naming standard for constants. As it stands it is only by looking at the declaration does one know a particular variable is a constant or not. My personal approach is to make all constants uppercase words delimited with underscore. It instantly identifies the constant and would help in maintenance. But for some reason it looks wrong in javascript, and prefixing or post fixing is a terrible naming habit. May be a question for another day. – Blindman67 Oct 31 '15 at 21:59
2

I think that the const keyword is often overused. It makes sense to use const everywhere if you strictly want to write pure functions (Functional Programming approach) but if you're not trying to be 100% adherent to the FP religion then I think that you should just use let. Personally, I use const for actual constants like const MAX_HEIGHT = 1234; also in Node.js I think that doing const fs = require('fs'); at the beginning of the file also makes sense.

It's one of those features which in theory is designed to protect developers from themselves but I don't particularly like refactoring code that overuses const; I keep having to rename const variables to let all the time - This can be a problem if you accidentally forget to change the declaration to let as it can lead to bugs when that code path executes.

In my opinion, if you use const, then you need to make sure that the variable is semantically a constant and will remain a constant in the foreseeable future. Also, I think that const sometimes gives a false sense of safety if it's overused. For example, you can do const obj = {}; then later modify the object obj.newProperty = 1234; - This is allowed because you're not changing the object reference itself but it does seem like it defeats the purpose of const somewhat.

Jon
  • 1,224
  • 2
  • 14
  • 23