09 May, 2009

The && and || operators.

In JavaScript, the && and || operators are used as short-hands for conditionals. For instance:

if (foo) {
    if (bar) {
    }
}
Can be written much more succinctly like this:
if (foo && bar) {
}
And:
if (foo) {
} else if (bar) {
}
Can be written like this:
if (foo || bar) {
}
That's great and all, but these two simple operators hold even more power to them. Let's look at exactly how they function:
  • && returns the first operand if it can be converted to false; otherwise, returns the second operand.
  • || returns the first operand if it can be converted to true; otherwise, returns the second operand.

The key thing to note here is the second clause. && and || do not always return boolean values! That works out okay, because JavaScript has the concept of truthy and falsy values, which is a fancy way to say that anything can be easily converted into true or false.

"What are you talking about? Why should I care about this?", you say. Let's look at some examples of code, and show how the && and || operators can help us out.

if (foo) {
    foo.bar();
}
Okay, looks simple enough. We don't know whether foo exists at runtime or not, so we have to wrap the statement foo.bar() in an if. However, the following code is identical:
foo && foo.bar();

"Huh? What's going on here?" As stated above, the && operator returns the second operand if the first operand is truthy. In addition, if the first operand is falsy, the second operand isn't even evaluated!

In other words: foo.bar() is only called if foo is truthy.

What exactly is truthy and falsy? A value in JavaScript is falsy if it is undefined, null, false, the empty string "", NaN, or the number 0.

Everything else is truthy, including an empty object {} and empty array [].

"Fine, so I can save a couple lines by using the && operator, who cares?"

Let's make this example a little more complicated by using a more deeply-nested object:

if (foo) {
    if (foo.bar) {
        if (foo.bar.qux) {
            foo.bar.qux.corge();
        }
    }
}
Oh my! Look at all the nested ifs! Now, we could have written it like this:
if (foo && foo.bar && foo.bar.qux) {
    foo.bar.qux.corge();
}
Or even more succinctly:
foo && foo.bar && foo.bar.qux && foo.bar.qux.corge();

Whichever you use will depend on your personal preferences. I'm not here to convince you to use the logical operators in this way, merely to point out that some people do use them this way. So next time you see something like the code above, you'll know what's going on, rather than being confused.

Now, the || operator can be used to select the "default" value of a variable. What do I mean by this? Well, imagine you have a function that accepts arguments, but some arguments are optional. Here's an example:

function foo(a, b, c) {
    if (!c) {
        c = 10;
    }
}
Now, there's nothing wrong with this, but you can save some characters by doing it like this:
function foo(a, b, c) {
    c = c || 10;
}

Using the above code, the variable c will supply the default value 10 if c is not specified when calling the function.

As stated above, my goal is not to convince you to use these techniques, merely to point them out so you'll understand what's going on when you read other people's code.

No comments:

Post a Comment