1

A colleague, and frankly better software engineer that me, is telling me that this pattern

let variable = someDefaultVariable();
if (some_boolean) {
    variable = someOtherValue();
}

is better than this pattern

let variable
if (some_boolean) {
    variable = someOtherValue();
} else {
    variable = someDefaultVariable();
}

My doubt about this is that the initial instantiation is going to involve a waterfall of function calls before the if block is hit, although he seems convinced that the first approach is better.

Speaking specifically about JavaScript, which of these patterns is better and more secure. Is this the same for C?

6
  • 2
    Has your colleague given you any reasons why the first approach is better?
    – Blrfl
    Mar 5, 2019 at 12:18
  • he said that the first assignment will create a pointer.
    – Joey Gough
    Mar 5, 2019 at 12:25
  • 4
    Both are horrific. The first assigns the variable then reassigns it, making the code harder to read and understand. The second declares it then waffles on with if and else to do the assignment. Just use the ternary operator, which simplifies the code and assigns (once) via the declaration.
    – David Arno
    Mar 5, 2019 at 12:26
  • 1
    @JoeyGough, "he said that the first assignment will create a pointer". No, it won't. Even if it did, how is creating a pointer supposed to be better?
    – David Arno
    Mar 5, 2019 at 12:27
  • 5
    Your coworker might be right about one JavaScript interpreter, but utterly wrong about the next. The ECMAScript standard does not do a deep dive into how memory should be allocated. Furthermore, there is so much runtime optimization in modern JavaScript interpreters that it frankly isn't worth the time micro optimizing something like this. Go for readability and correctness. Mar 5, 2019 at 12:33

2 Answers 2

13

This is more of a style issue than anything else, and very susceptible to personal opinion.

The second example in the question more clearly shows intent, which increases the readability of the code, however with the first example, there is no way to have the variable become uninitialised by further code changes breaking the code.

You can however sidestep the problem entirely by defining it explicitly with a conditional operator (ternary):

let variable = some_boolean ? someDefaultVariable() : someOtherValue();

It's less commonly used, but should be in every programmer's toolbox for tasks like this. It shows both intent, and is 'cleaner' (less boiler-plate, and variable cannot be unassigned) which I suspect is the reason your colleague prefers the first form.

This answer would not be any different for C, which is actually my background, or most any other language, for that matter.

12
  • 1
    +1, but you don't need to surround the ternary statement with parenthesis This works well when there is a default and only 1 other value. This breaks down if there are 3 or more possible values. Mar 5, 2019 at 12:25
  • 2
    The answer would be slightly different for all languages which support unmodifiable variables (e.g. const in TypeScript and C++, final in Java, val in Scala), because it adds another, and perhaps the strongest, argument in favour of the direct initialisation approach. You cannot make a variable const/final/val otherwise. Mar 5, 2019 at 12:41
  • 1
    If you coding style prohibits ? : , then you can extract this to a function and use returns in an if. If your coding style also prohibits multiple return statements, then you are pretty much stuffed.
    – Caleth
    Mar 5, 2019 at 12:55
  • 1
    @ChristianHackl Java's final is better understood as “assigned exactly once”, not as “cannot be changed after the declaration”. If OP's second example were Java, the variable could be final and the compiler would ensure that all paths initialize the variable. In most other languages you are right though that something like a ternary would be preferable.
    – amon
    Mar 5, 2019 at 13:56
  • 8
    @Caleth: If you actually have such a coding style, then any attempt to produce good and readable code is very likely doomed anyway. Mar 5, 2019 at 14:03
4

With the first approach you have a variable that is initialized to a value the moment it is created. Adding additional lines between the declaration and if statement means you have some meaningful information already in the variable.

let variable = someDefaultVariable();

// We know `variable` is some sort of default value, so we
// can predict a sensible result
let variable2 = variable + 3;

if (some_boolean) {
    variable = someOtherValue();
}

Contrast that with the second example where adding lines of code in between the variable declaration and the first if statement ends up working with an uninitialized value:

let variable;

// Here `variable` is undefined, so we get a NaN result at
// run time, but while your coworkers are reading this code
// they might think it will result in a number.
let variable2 = variable + 3;

if (some_boolean) {
    variable = someOtherValue();
} else {
    variable = someOtherValue();
}

Code evolves. Leaving variables uninitialized leaves little potholes in the roadway that is your programming logic. It's all to easy to miss things like this when changing code — especially someone else's code.

Go for:

  1. Correctness (making sure variables are initialized to something is part of "correctness")

  2. Readability and understandability

Since this is JavaScript, do not go for optimizing for memory usage or memory layout.

This sort of thing does not exist in the ECMA Script spec, mostly so JavaScript interpreters can have free reign to optimize as they see fit.


As mentioned in another answer and in comments, the ternary operator can make this a one-liner, which you can split into multiple lines for readability:

let variable = some_condition
    ? someValue()
    : someOtherValue();

This becomes unreadable when the variable has 3 or more possible values upon initialization. In that case you can always put the calculation of the initial value into another function:

let variable = calculateValue(some_condition);

And then calculateValue gets to deal with the if statement:

function calculateValue(condition2) {
    if (condition1) {
        return value1;
    }
    else if (condition2) {
        return value2;
    }

    return defaultValue;
}
2
  • 1
    I'd strongly vote against your first example, where the someDefaultVariable() value gets used even in cases where the correct one is someOtherValue() (because of some_boolean being true). Mar 5, 2019 at 19:40
  • @RalfKleberhoff: I would prefer a ternary expression, as noted in another answer, or defining a function that returns the proper value so the variable does not remain uninitialized. Mar 5, 2019 at 19:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.