Variables

  • 13.1 Always use const or let to declare variables. Not doing so will result in global variables. We want to avoid polluting the global namespace. Captain Planet warned us of that. eslint: no-undef prefer-const

    1. // bad
    2. superPower = new SuperPower();
    3. // good
    4. const superPower = new SuperPower();

  • 13.2 Use one const or let declaration per variable. eslint: one-var

    Why? It’s easier to add new variable declarations this way, and you never have to worry about swapping out a ; for a , or introducing punctuation-only diffs. You can also step through each declaration with the debugger, instead of jumping through all of them at once.

    1. // bad
    2. const items = getItems(),
    3. goSportsTeam = true,
    4. dragonball = 'z';
    5. // bad
    6. // (compare to above, and try to spot the mistake)
    7. const items = getItems(),
    8. goSportsTeam = true;
    9. dragonball = 'z';
    10. // good
    11. const items = getItems();
    12. const goSportsTeam = true;
    13. const dragonball = 'z';

  • 13.3 Group all your consts and then group all your lets.

    Why? This is helpful when later on you might need to assign a variable depending on one of the previous assigned variables.

    1. // bad
    2. let i, len, dragonball,
    3. items = getItems(),
    4. goSportsTeam = true;
    5. // bad
    6. let i;
    7. const items = getItems();
    8. let dragonball;
    9. const goSportsTeam = true;
    10. let len;
    11. // good
    12. const goSportsTeam = true;
    13. const items = getItems();
    14. let dragonball;
    15. let i;
    16. let length;

  • 13.4 Assign variables where you need them, but place them in a reasonable place.

    Why? let and const are block scoped and not function scoped.

    1. // bad - unnecessary function call
    2. function checkName(hasName) {
    3. const name = getName();
    4. if (hasName === 'test') {
    5. return false;
    6. }
    7. if (name === 'test') {
    8. this.setName('');
    9. return false;
    10. }
    11. return name;
    12. }
    13. // good
    14. function checkName(hasName) {
    15. if (hasName === 'test') {
    16. return false;
    17. }
    18. const name = getName();
    19. if (name === 'test') {
    20. this.setName('');
    21. return false;
    22. }
    23. return name;
    24. }

  • 13.5 Don’t chain variable assignments. eslint: no-multi-assign

    Why? Chaining variable assignments creates implicit global variables.

    1. // bad
    2. (function example() {
    3. // JavaScript interprets this as
    4. // let a = ( b = ( c = 1 ) );
    5. // The let keyword only applies to variable a; variables b and c become
    6. // global variables.
    7. let a = b = c = 1;
    8. }());
    9. console.log(a); // throws ReferenceError
    10. console.log(b); // 1
    11. console.log(c); // 1
    12. // good
    13. (function example() {
    14. let a = 1;
    15. let b = a;
    16. let c = a;
    17. }());
    18. console.log(a); // throws ReferenceError
    19. console.log(b); // throws ReferenceError
    20. console.log(c); // throws ReferenceError
    21. // the same applies for `const`

  • 13.6 Avoid using unary increments and decrements (++, --). eslint no-plusplus

    Why? Per the eslint documentation, unary increment and decrement statements are subject to automatic semicolon insertion and can cause silent errors with incrementing or decrementing values within an application. It is also more expressive to mutate your values with statements like num += 1 instead of num++ or num ++. Disallowing unary increment and decrement statements also prevents you from pre-incrementing/pre-decrementing values unintentionally which can also cause unexpected behavior in your programs.

    1. // bad
    2. const array = [1, 2, 3];
    3. let num = 1;
    4. num++;
    5. --num;
    6. let sum = 0;
    7. let truthyCount = 0;
    8. for (let i = 0; i < array.length; i++) {
    9. let value = array[i];
    10. sum += value;
    11. if (value) {
    12. truthyCount++;
    13. }
    14. }
    15. // good
    16. const array = [1, 2, 3];
    17. let num = 1;
    18. num += 1;
    19. num -= 1;
    20. const sum = array.reduce((a, b) => a + b, 0);
    21. const truthyCount = array.filter(Boolean).length;

  • 13.7 Avoid linebreaks before or after = in an assignment. If your assignment violates max-len, surround the value in parens. eslint operator-linebreak.

    Why? Linebreaks surrounding = can obfuscate the value of an assignment.

    1. // bad
    2. const foo =
    3. superLongLongLongLongLongLongLongLongFunctionName();
    4. // bad
    5. const foo
    6. = 'superLongLongLongLongLongLongLongLongString';
    7. // good
    8. const foo = (
    9. superLongLongLongLongLongLongLongLongFunctionName()
    10. );
    11. // good
    12. const foo = 'superLongLongLongLongLongLongLongLongString';

  • 13.8 Disallow unused variables. eslint: no-unused-vars

    Why? Variables that are declared and not used anywhere in the code are most likely an error due to incomplete refactoring. Such variables take up space in the code and can lead to confusion by readers.

    1. // bad
    2. var some_unused_var = 42;
    3. // Write-only variables are not considered as used.
    4. var y = 10;
    5. y = 5;
    6. // A read for a modification of itself is not considered as used.
    7. var z = 0;
    8. z = z + 1;
    9. // Unused function arguments.
    10. function getX(x, y) {
    11. return x;
    12. }
    13. // good
    14. function getXPlusY(x, y) {
    15. return x + y;
    16. }
    17. var x = 1;
    18. var y = a + 2;
    19. alert(getXPlusY(x, y));
    20. // 'type' is ignored even if unused because it has a rest property sibling.
    21. // This is a form of extracting an object that omits the specified keys.
    22. var { type, ...coords } = data;
    23. // 'coords' is now the 'data' object without its 'type' property.