loading...

There's no "else if" in JS

Fabio Russo on May 20, 2018

Grammar is not a joke... Exactly, in Javascript's grammar there's no else if statement. How many times have you used it before? Why I... [Read Full]
markdown guide
 

There is a golden rule: if statement is always a sign of a design flaw. Period.

 

LOL
I guess technically, if statements could have been omitted in this example (though there’d still be a conditional present).

function wow(arg){
  var o = {
    dog: "LOVELY",
    cat: "CUTE"
  };
  return o[arg] || "gimme an animal";
}

wow("cat");
 

I think above code needs one more condition.

function wow(arg){
  var o = {
    dog: "LOVELY",
    cat: "CUTE"
  };
  return (o.hasOwnProperty(arg) && o[arg]) || "gimme an animal";
}

wow("cat");

If I want to replace above code. I would do something like this. (with conditions)

const wow = arg => (
  (arg === "dog" && "LOVELY") ||
  (arg === "cat" && "CUTE") ||
  "gimme an animal"
);

wow("cat");

can someone explain to me why you can use parathesis instead os curly braces with an arrow function? I was thought that the parathesis are used to indicate to the compiler that what is encapsulated in the parathesis are supposed to be treated as parameters, and what is in the curly braces are supposed to be treated as the logic.

This goes to the point trying to be made by Fabio Russo "the good parts or right ways to code...It's not really the best way."

Your information is not incorrect for regular functions. However, with an arrow function, you are allowed to use parentheses to represent a function body with a single statement (useful when spanning multiple lines).

There are other places you can omit things as well.

Examples:

Single parameter, parentheses are optional

const myFunc = (singleParam) => {/* function body */};
// is the same as
const myFunc = singleParam => {/* function body */};

Multiple parameters require parentheses

const myFunc = (param1, param2) => {/* function body */};
const myFunc = param1, param2 => {/* function body */}; //Syntax error due to missing parentheses

Function body needs curly braces for multi-line command block

const myFunc = param1 => {
  console.log('I did something');
  console.log('I did something else');
};

However, if your body is a single line and you want to return the result, you may do any of the following (all of these return the value of name.toUpperCase()

const myFunc = name => {
  return name.toUpperCase(); // note the return
};

const myFunc = name => (
  name.toUpperCase(); // note, no return if in parentheses
);

const myFunc = name => name.toUpperCase();

It really helps if you have a command that spans multiple lines where you just want to return the result. So, for example, if you were dealing with a promise you could do either of the following:

const fetchUser = userId => (
  fetch(`http://example.com/user/${userId}`)
    .then(rsp => rsp.data)
    .catch(error => {
      console.log(error);
    };
);

const fetchUser = userId => {
  return fetch(`http://example.com/user/${userId}`)
    .then(rsp => rsp.data)
    .catch(error => {
      console.log(error);
    };
};

Now, I understand that you're able to use arrow functions in more diverse ways, but after looking at the code I had trouble with I realize that pranay rauthu used a "hidden if-statement" how does one use the ampersand(&) to make a conditional, and to see if arg === some-value, and print a value based on what the client set arg equal to.

If someone has a response to my question, please point me to some resource so I can deepen my knowledge on javascript

 

I believe you misunderstand what “design flaw” means. The necessity to choose between "LOVELY" and "CUTE" inside a single function in the aforementioned example is already a problem.

One cannot overcome a poor design issues just re-writing this single function in a weird way.

Can you provide an example of a good solution please!

Can you state the problem to be solved in the first place? There is no silver bullet, nor a pill. I just stated that every single problem might be better solved without ifs.

Actually I didn’t misunderstand. I was really just having a little coding fun at your expense because I disagree with your statement. Personally, I believe that anyone that states something along the lines of “never do xyz no matter the circumstance” (not your exact words, I know) has a flawed approach to design and development. Decision/branching is a normal part of what we do. Whether you use an if statement or some other form becomes trivial in the grand scheme. I agree that it is not always the best way but equally disagree that it is always wrong.

 
 
 

How can you have any flow control without some sort of if-statement?

E.g. with FSMs. E. g. with class hierarchy. E.g. with pattern matching. The list might be easily prolonged.

But surely some tasks just require if-statements? What if you receive an integer from user input and want to know if it is positive or not? What if you want to filter out all odd numbers out of a list? Isn't pattern matching on something with two cases just an if-statement with the first case as a condition?

Not really. Well, sometimes, very rare.

What if you receive an integer from user input and want to know if it is positive or not?

This might happen in some beginners’ exercise, not in the real life. I won’t allow users to input both positives and negatives the same way and I would immediately raise on any unexpected input.

What if you want to filter out all odd numbers out of a list?

I would use the standard library filter function/method, like (Elixir example, but it does not matter, the same is available in Ruby, Python, Perl for sure): Enum.filter(input, &is_odd(&1)).

Isn't pattern matching on something with two cases just an if-statement with the first case as a condition?

Pattern matching has many clauses by default, hence the code might be easily extended when needed, unlike if. Also, pattern matching is significally faster. And, the last but not the least, I usually don’t have to choose between two conditions in the middle of the code, because I think about the proper design upfront.

Alright, but then you are just hiding the if-statement within the is_odd method. There is no sane way to implement these types of functions, that take an integet and return a boolean, without if-statements.

I highly doubt that pattern matching can be faster than if-statements in any language, since pattern matching on non-enum types would have to be implemented using conditional jumps (i.e. if-statements) in the underlying machine code or VM code.

I never said I am advocating the senselessness of conditional jumps in the underlying assembly / machine codes. That is obviously impossible.

What I said is if statement as it is, is hardly maintainable.

Hey Aleksei! I'm really interested to know more about your vision about this subject. I'd love to read an article about that. If you have some time to write about this, I would be really glad! :)

I will do, sooner or later. The subject actually bugs me :)

That'd be nice. A lot of this discussion is what not to do, but that isn't worth much without alternatives and example use cases.

Alright, but then you are just hiding the if-statement within the is_odd method. There is no sane way to implement these types of functions, that take an integet and return a boolean, without if-statements.

To be fair - one could also claim that if statements are just hiding the conditional jumps. Creating better abstractions over problematic implementations is a virtue.

That was my point, Idan; if-statements are just conditional jumps, and you need those to be Turing complete. I disagree with the idea that if-statements are always a design flaw, because that just leads to using overabstracted solutions for simple problems, e.g. using pattern matching on a boolean condition.

I agree with your virtue, I just don't see something as integral as the if-statement as a 'problematic implementation'.

I understand whose is in the functional is alergic to IF statement, but a coder can create a good program without a functional approach. Many developers write code in procedural mode, if you use GNU/Linux you'll know that in many files you'll find IF statements

One might use Linux for decades and never ever see a single line of the code.

That’s true, there are very specific circumstances under which if might be the best choice, but all those are exceptional nowadays. 99% of businesses use high-level languages and in high-level language, no matter whether it’s functional or not, ifs are a sin.

99% of businesses ????????
If you consider that COBOL has been back ...
If you consider that many banks prefer continue with old COBOL (not the new one) for the ATM services.
I you consider that big manifactures build products IoT with a poorly code and very buggy.
I think that you're developing for excelence, despite I've seen in your code of elixir-iteraptor some IF statement

Legacy is legacy, there is no doubt (although COBOL was invented as a most imperative language ever.) I admit I exaggerated the percentage, though.

I've seen in your code of elixir-iteraptor some IF statement

I never said I am perfect. If I had 72hrs/day I would be always writing the good code avoiding ifs. This is a solid settlement: I use ifs to save some time, while I still expressly understand I could do better.

I'm intrigued by what you said about if-statements. I'm curious to know how you would write the following callback function.

someRequest(URL, (err, result) => {
    if (err) {
        console.log(err);
    } else console.log(result);
}

I'm still a novice so it's difficult for me to imagine doing some things without if-statements. I would appreciate it if you could show me😅🙂.

You could use something like promises.

someRequest(URL)
.then(result => console.log(result))
.catch(err => console.log(err));

Ooh. That's right. Forgot promises could do that😅. Thanks 😊

 

Then why is it there in the language? To put in other words, where does it make sense to use an if-else statement?

 

Saying that if-else statement are always bad isn't something I would do. As any other tools, it has to be use in the right place to be effective.
Sometimes, I do prefer a switch (or match expression). But sometimes, it just do not make any sense to avoid the if-else. As an example, when coding a game, you might want to know either or not an object is in front of the player. You will certainly use the dot product as it is cost efficient and then you will have to test if the result is zero or if it is a positive number above zero.
From my point of view, the if-else fits perfectly here. Again, his use has to be cautious.

At least, I think so.

 

There are many things in modern languages that are just a matter of legacy. In procedural programming era (the most noticeable example would be FORTRAN) there were no paradigms to avoid conditionals. Nowadays we have plenty.

Using ifs inevitably leads to spaghetti code, that is hard to read and incredibly hard to maintain. Also, if violates the SRP principle out of the box.

Yes, sometimes if might be the best solution (when there are two possible outcomes, and there will be two forever, e.g. if hours < 12 then 'AM' else 'PM',) but the list of usages is very limited and in general there [nearly] always would be a better, cleaner and easier to support alternative.

This is incorrect. The inclusion of if isn't a matter of legacy, it's because if is a low level primitive that can be used to build higher level abstractions. That is why Lisp has if; the thesis of Lisp is to expose a small set of primitives, allowing developers to leverage those primitives to build the language they need. While I agree that many developers reach for if when a higher level of abstraction would be more appropriate, there should be no golden rule to "never use if". Sometimes a lower level of abstraction is what is appropriate for a task.

 

While I don't agree wth the premise that if is inherently bad in a non-functional programming language, having something in a language doesn't make it good. Many languages are extremely poorly-thought-out and nothing's perfect.

 

This is really baffling me. What is the alternative? I don't think programming languages can be Turing complete without some sort of if-statement.

The only realistic way I can interpret your comment is that we should only use switch-statements, but that would just lead to

switch (condition)
{
  case true: ...
}
 

Switch is the way to implement the "else if" construct :)

 

My point was not about using if statement ... I just used that, because It's a starting point for everyone.
Most of use learn through cycle and conditional and variables... and most of the time, we just follow the rules. That was the point, not encouraging to use poor design.

 
 

Here are two real-world pieces of code I wrote yesterday. I describe the problem I'm solving, link to the relevant resources that led me to write that code, and include the if statement laden code I wrote. Your absolutism and your certainty has me rolling my eyes, so go ahead and prove me wrong! Rewrite my code without if statements in a way that's better: gist.github.com/JoshCheek/71623a73...

 
 

In FP you could use filter instead of if, which makes your code more modular than stacking if on if.

In FP you could use filter instead of if

“In FP” preamble looks redundant here. All modern languages (save for, maybe, Malbolge,) allow filtering over stacked ifs.

The point I wanted to make was, "if you choose to do FP in your PL of choice you would use filter instead of if"

Unlike Haskell, JavaScript is not a purely functional language. Functions such as filter are recent additions to the language. If you look at the V8 source code for the filter function, you'll see this comment: "The following functions cannot be made efficient on sparse arrays while preserving the semantics."

github.com/v8/v8/blob/73c9be9b31d2...

That’s mostly not a matter of efficiency, it’s all about clean code.

 

I don't understand how this could be true :/

 

I don't think one can design a computer without any logic gate. And, transformation doesn't change how a thing is designed.

 
 

Cool point. In cases like this, I often forgo the else altogether because of the return statements.

function wow(arg){

  if(arg === "dog") return "LOVELY";

  if(arg === "cat") return "CUTE";

  return "gimme an animal";
}

wow("cat");

Still, your point about understanding the why behind what we write is an important one. Thanks for sharing.

 

A function with only ifs that return is just the missing-from-JS pattern matching+guards syntax.

 

Another blind gospel: braces around if-statements imply that people don't understand what braces do (they turn a group of statements into a single statement). So rules like "always put braces around the body of your if-statement" get it backwards, it'd be like wrapping every value in an array, because maybe you'll want more than one of them, someday.

This brings us to the the three-brace rule: if you're going to make me put one brace where I don't need it, then I'm going to add two more.

function wow(arg) {{{
  if(arg === "dog") {{{
    return "LOVELY"
  }}} else if(arg === "cat") {{{
    return "CUTE"
  }}} else {{{
    return "gimme an animal"
  }}}
}}}
console.log(wow("cat"))           // => CUTE
console.log(wow("dog"))           // => LOVELY
console.log(wow("hat-log"))       // => gimme an animal

Now, in people's defense, JavaScript's syntax is terrible, it's absurd that this works (when it would be so much more useful to have toplevel objects), and given that it works, it's absurd that you can't drop the braces around function bodies.


And the other super obnoxious mostly un-understood rule: littering semicolons all over the code. Literally after every line that they can, rather than before the ones that cause the problems. It's especially misguided b/c it masks the actual problem lines, and it gives a false implication that omitting the semicolon would mean it continues on the next line. But that isn't true, JS doesn't need a semicolon to terminate the line, only to terminate it early. The reason you stick them at the end is b/c sometimes the next line says "oh hey... Imma tag along with the previous line", so with this dumb rule, every line has to guard against an aggressive next line.

log = text => { console.log("logged: " + text); return log }
log("loggin stuffs")

// and now for some math
(2+2)
(3+3)
 

I agree it's interesting that you can't drop the braces around function bodies (which hadn't occurred to me before) but the example in the post, of where else if ... is actually else { if ... } seems obvious. Isn't that behaving exactly how it's written, and isn't that how everyone would expect it to work if they'd never seen the language before?

 

It's not.
Because we're always encouraged to use {} in some ways, and we learn by memory to use those, without knowing the why.
During the first approach to a language, you cannot be so deeply analytic, because you've to trust the rules, or you will never go on.
After the totally beginner phase, you should start to ask yourself the why.

Have you ever encountered a bug caused by missing parentheses? Being consistent improves code readability and makes it easier to identify bugs.

It's not about... DON'T USE PARENTHESES :D It's all about know the why of parentheses

 

Now, in people's defense, JavaScript's syntax is terrible, it's absurd that this works (when it would be so much more useful to have toplevel objects), and given that it works, it's absurd that you can't drop the braces around function bodies.

I know what you're talking about.
But do we know, why It's still working?
It's working because of blocks.
You're creating blocks, inside blocks... inside blocks.

That's important in JS, because of the lexical-scope.

I'm not saying that's ok ... I'm just saying that in JS It works like that, not just because It's bad

 

Apparently I didn't use the word block in there, but yes, I understand this :)

If you want to be really irritated with JS, figure out what's going on with these examples (hint)

$ node -p '{a: {b: 1}}'
1

$ node -p '({a: {b: 1}})'
{ a: { b: 1 } }
 

Without braces, how would the interpreter / a fellow developer know where the function ends? If you write

function foo(x)
  console.log(x)
console.log("Hello")
foo("Hello")
foo("Hello")

then how often are you expecting to see Hello logged? Three times? Four times? Zero times? An unbounded number of times due to recursion?

Some languages use whitespace or end, but I find the braces to be more readable and less error prone.

 

I'd expect three times. The function foo(x) would receive the next syntactic element as its body, which is console.log(x). Not because of indentation, but because it's the next expression. If you wanted more than one expression, you would use the braces to make a block, which would group the multiple expressions into one. Then it would be consistent with the way we use blocks on if statements.

Oh, also note that this is how fat arrows work:

const foo = x =>
 console.log(x)
console.log("Hello")
foo("Hello")
foo("Hello")
 
 

This is a good point, and I think we could write some much longer posts on some of these practices.

I appreciate how this points out how important the "why" is of many of these patterns and practices.

I've been developing in JS since nearly the beginning and many of these "best practices", that are somehow still mainstream, are for problems that no longer exist.

Since people often don't know why we did them, they continue to persist them because all the Sr. Devs told them to years ago.

The "why" is so important to know.

 

I've been developing in JS since nearly the beginning and many of these "best practices", that are somehow still mainstream, are for problems that no longer exist.

Since people often don't know why we did them, they continue to persist them because all the Sr. Devs told them to years ago.

This is so true of so many areas of software development. Workarounds become best practice and stay that way long after they are needed.

 

It's easy to make fun of the cargo cults, only to eventually realize you've become one. Some don't make it that far.

 

Thanks for the write-up. This kinda reminds me of that beginner's guide to shell scripting article that opened our minds to the fact that when we use if brackets in bash we're actually using test ;).

 

While everyone is busy pointing out flaws in if~else, It seems that I don't get the point of this post.

Fabio Russo (or Anyone), can you please give me one edge case when knowing that there is no "else if" would actually create any noticeable difference in any possible way.

If it just happens to be a trivia, we can extend this argument to anything in Javascript.

Like there is no Javascript but just machine code :?

 

Hm, It seems that you've not read all the post.
At some point I wrote:

I'm not writing this post, just because It's something really curious to know.
I'm writing this to make you think about all the good parts or right ways to code, that forces you to write code in a way, that sometimes It's not really the best way.

It's just a:
see? You're using this, but you dunno how It works. Why are you using It? Because someone told you to do so? Or what?

 

But you can continue digging how it works till you reach the bits of a processor.

I get it you can write ‘if’ ‘else if’ ‘else’ with just ‘if’ ‘else’. And from reading your post it seems the browser might be internally doing it.
But what is the actual value in this revelation.
By no means I am trying disrespect this post, just trying to understand the point.

For the sake of argument one can even write everything with Bitwise OR, AND operator, but we don’t see people writing about it.

I'm NOT explaining HOW it works :D
I'm trying to discuss about, all the time we code by rules without knowing the why

 

Good point, buy maybe you should change your example so you don't use the return clause.

I feel like refactoring your example to:

function wow(arg){
  if (arg === "dog") return "LOVELY";
  if (arg === "cat") return "CUTE";

  return "gimme an animal";
}
 

You also realize it when you want to use the shorthand.
On the shorthand syntax there is no "else if". You have to write this instead:


(arg === "dog" ? "LOVELY" : (arg === "cat" ? "CUTE" : "gimme an animal"))

 

This not new or unique to JS. It's how else-if has been since C. It's a testament to the simplicity of a minimalist language definition:

Where acceptable statements are:

if ( expression ) statement
if ( expression ) statement else statement
 

Ok, but still, lots of people do It without knowing the why.
That's the point.

 

"there is a golden rule"... Sometimes I sacrifice efficiency for readability, sometimes I do the opposite. To say one size fits all is arrogant, narrow minded and not teaching good practices. There should be a good reason to do everything we do, even if it is not the most appropriate it can still be the correct choice for that instance

 

The second code block is wrong, if you would like to show all the brackets.

This is the corrected code block:

function wow(arg){

  if (arg === "dog") {
    return "LOVELY";
  }

  else {

    if (arg === "cat"){
        return "CUTE";
    } 

    else {
      return ("gimme an animal");
    }
  }
}

The weird spacing is for demonstration: else is a keyword, working in pair with if. The reason why it's not noted like this is obvious: the else-blocks stack up a hierarchy, so that multiple else-if conditionals would add indentation and make the code unreadable with each additional condition. else-if is a construction to make such stacks more readable by taking away the need for stacking.

I myself recommend to hold brevity over the subtleties and nuances of syntax:

function wow(arg) {

  if(arg === "dog")
    return "LOVELY";

  if(arg === "cat")
    return "CUTE";

  return "gimme an animal";
}

Of course, this code would be harder to mutate in a patch. When the first condition would not return a string but alter the variable arg to "cat", the second condition would match and execute its code, while that would not happen when that condition would be else-enclosured. And eventually, the last line only works as the default case because the former conditionals end with their respective return themselves.

But that's why you got to think when you code.

 
 

I would use const instead of var though (if you're gonna go es6).

And just for shits and giggles, the fn could be done as a one-liner:

const wow = arg => ({dog: "LOVELY", cat: "CUTE"}[arg] || "gimme an animal");
wow("cat");
 
 

Does anyone know if this is JS-specific or not? Braceless if-statements exist in most languages and now I'm curious if those languages have else-if explicitly defined in their grammars or not.

 

Yes, as far as I know this is how a lot of languages, at least most "C-Style language" will do this. You can also look at the grammar of a lot of languages and figure out from there that it would have to do that as else if is not being defined as one keyword. They are separate keywords.

The same is also in python with elif, which j believe is actually just syntatic sugar in the end, and would end up producing the same code.

 

I believe it's also true for C / C++ / Java. I didn't go check just now, but it has always been my understanding that this was how they worked.

 
 

Whoa! Mind=Blown.

I'm a huge fan of else if. I used it at least 5 times today alone.

 

Great article! I especially like the last part. Always care about your knowledge -my emphasis. Very good point! It is easy to follow along, it is hard to know why. Knowing the why is the best part!

 

Knowing the why... should be the why we love to code!

 

I mean, else if is syntactic sugar for else { if ... } as opposed to being a special language construct (like Python's elif), but it does exactly the same thing. You could write basically the same article about how C pointers are just integers, or about how a switch statement is just syntactic sugar for something nasty-looking with goto, or any number of things. A more honest post might talk about how a CPU can't execute JavaScript, so it gets translated into machine code - else if and else { if look the same at that level, since they mean the same thing. Which one is syntactic sugar for the other doesn't really matter, and, as others have mentioned in this thread, I'd argue that actually the else { if version adds an additional language construct (which is why if (true) alert('alert!') works) and is therefore the more honest version.

 

And the folk thinks that PHP syntax is rubbish? When in JS you can use ; or not at all? Or many coders sometimes use var or not at all. Ignoring the importance of var ... If you speak of JS you cannot say "Grammar is not a joke"

 

Nope... I don't agree.
If you know grammar, you know where to use ";" and where to use "var".
If you dunno It, you just code by memory.

 
 

Thanks.
Love to share ideas.
Lots of people think of JS as a “bad” language... most of the time, we dunno It.
That’s all.

 

JS language + ecosystem is one of the most interesting areas of software these days. "Good or bad", it's probably worth learning the finer details.

 

function wow(arg)
{
if (arg === "dog") return "LOVELY";
if (arg === "cat") return "CUTE";
return ("gimme an animal");
}

wow("cat");
//-> "CUTE"
// or

function anotherWow()
{
return (arg === “dog”) ? “LOVELY”:((arg === “cat”) ? “CUTE”:”gimme an animal”);
}
anotherWow(“cat”);

 
 

The brackets, if you put them in, do a great job of showing why the conditions up to a success are evaluated, but the ones after aren't.

No, I don't mean leaving brackets in your code is okay, I meant it as an exercise.

 
 
 

"dont do this.. dont do that.."
THE"if" you gonna need it.. wether your boss,your mentor, your mom tell you not to do so.

 

Please re-read: w3schools.com/js/js_if_else.asp

Use else if to specify a new condition to test, if the first condition is false.

 

Isn't the second else supposed to be outside at the same level as the first else?

if(){
}else{
if{}
}else{
return{}
}

 

No, because that would not result in a meaningful execution branch; if we abstract away the code inside the braces we get

if (condition)
{
  foo();
}
else
{
  bar();
}
else
{
  baz();
}

but what would that mean? When would baz() ever be called?

 
 

Is It.
The JS grammar has no else if statement.

code of conduct - report abuse