58

Why do these logical operators return an object and not a boolean?

var _ = (obj.fn && obj.fn() ) || obj._ || ( obj._ = {} ); var _ = obj && obj._; 

I want to understand why it returns result of obj.fn() (if it is defined) OR obj._ but not boolean result.

6
  • 10
    I think he wants to know why a || b doesn't return a boolean but a or b. Commented Mar 24, 2011 at 10:52
  • 1
    Doesn't var _ = obj && obj._; return a bool? O.o / Then what does it return? The first one evaluating as false evt. the last true if all are true? Commented Mar 24, 2011 at 11:05
  • ThiefMaster, that is exactly what I meant. I UPDATED my post Commented Mar 24, 2011 at 11:05
  • 1
    Answered here stackoverflow.com/questions/2851404/… Commented Mar 24, 2011 at 11:10
  • 1
    @theateist That's how && and || work in JavaScript. They return the arguments and not a Boolean value. .... Why you ask? Because Brendan Eich said so! Commented Mar 24, 2011 at 15:22

9 Answers 9

78

In JavaScript, both || and && are logical short-circuit operators that return the first fully-determined “logical value” when evaluated from left to right.

In expression X || Y, X is first evaluated, and interpreted as a boolean value. If this boolean value is “true”, then it is returned. And Y is not evaluated. (Because it doesn’t matter whether Y is true or Y is false, X || Y has been fully determined.) That is the short-circuit part.

If this boolean value is “false”, then we still don’t know if X || Y is true or false until we evaluate Y, and interpret it as a boolean value as well. So then Y gets returned.

And && does the same, except it stops evaluating if the first argument is false.

The first tricky part is that when an expression is evaluated as “true”, then the expression itself is returned. Which counts as "true" in logical expressions, but you can also use it. So this is why you are seeing actual values being returned.

The second tricky part is that when an expression is evaluated as “false”, then in JS 1.0 and 1.1 the system would return a boolean value of “false”; whereas in JS 1.2 on it returns the actual value of the expression.

In JS false, 0, -0, "", null, undefined, NaN and document.all all count as false.

Here I am of course quoting logical values for discussion’s sake. Of course, the literal string "false" is not the same as the value false, and is therefore true.

Sign up to request clarification or add additional context in comments.

2 Comments

That's all true, but doesn't answer the question. He asked "why".
also "undefined" don't only count as false, especially in the case of a variable not being defined, trying to evaluate that may lead to errors...
77

In the simplest terms:

The || operator returns the first truthy value, and if none are truthy, it returns the last value (which is a falsy value).

The && operator returns the first falsy value, and if none are falsy, it return the last value (which is a truthy value).

It's really that simple. Experiment in your console to see for yourself.

console.log("" && "Dog"); // "" console.log("Cat" && "Dog"); // "Dog" console.log("" || "Dog"); // "Dog" console.log("Cat" || "Dog"); // "Cat"

1 Comment

Your answer is really the most simple to understand. Thanks.
18
var _ = ((obj.fn && obj.fn() ) || obj._ || ( obj._ == {/* something */}))? true: false 

will return boolean.

UPDATE

Note that this is based on my testing. I am not to be fully relied upon.

It is an expression that does not assign true or false value. Rather it assigns the calculated value.

Let's have a look at this expression.

An example expression:

var a = 1 || 2; // a = 1 // it's because a will take the value (which is not null) from left var a = 0 || 2; // so for this a=2; //its because the closest is 2 (which is not null) var a = 0 || 2 || 1; //here also a = 2; 

Your expression:

var _ = (obj.fn && obj.fn() ) || obj._ || ( obj._ = {} ); // _ = closest of the expression which is not null // in your case it must be (obj.fn && obj.fn()) // so you are gettig this 

Another expression:

var a = 1 && 2; // a = 2 var a = 1 && 2 && 3; // a = 3 //for && operator it will take the fartest value // as long as every expression is true var a = 0 && 2 && 3; // a = 0 

Another expression:

var _ = obj && obj._; // _ = obj._ 

4 Comments

experimentX, I UPDATED my post. It returns one the result of fn or obj._ but not boolean.
you can also use !!x to force x to boolean
Or simply var _ = !!((obj.fn && obj.fn() ) || obj._ || ( obj._ == {/* something */}));
8

In most programming languages, the && and || operators returns boolean. In JavaScript it's different.


OR Operator:

It returns the value of the first operand that validates as true (if any), otherwise it returns the value of the last operand (even if it validates as false).

Example 1:

var a = 0 || 1 || 2 || 3; ^ ^ ^ ^ f t t t ^ first operand that validates as true so, a = 1 

Example 2:

var a = 0 || false || null || ''; ^ ^ ^ ^ f f f f ^ no operand validates as true, so, a = '' 

AND Operator:

It returns the value of the last operand that validates as true (if all conditions validates as true), otherwise it returns the value of the first operand that validates as false.

Example 1:

var a = 1 && 2 && 3 && 4; ^ ^ ^ ^ t t t t ^ last operand that validates as true so, a = 4 

Example 2:

var a = 2 && '' && 3 && null; ^ ^ ^ ^ t f t f ^ return first operand that validates as false, so, a = '' 

Conclusion:

If you want JavaScript to act the same way how other programming languages work, use Boolean() function, like this:

var a = Boolean(1 || 2 || 3);// a = true 

Comments

5

You should think of the short-circuit operators as conditionals rather than logical operators.

x || y roughly corresponds to:

if ( x ) { return x; } else { return y; } 

and x && y roughly corresponds to:

if ( x ) { return y; } else { return x; } 

Given this, the result is perfectly understandable.


From MDN documentation:

Logical operators are typically used with Boolean (logical) values. When they are, they return a Boolean value. However, the && and || operators actually return the value of one of the specified operands, so if these operators are used with non-Boolean values, they will return a non-Boolean value.

And here's the table with the returned values of all logical operators.

1 Comment

succinct and useful answer, with links to deeper resources. Would accept.
3

I think you have basic JavaScript methodology question here.

Now, JavaScript is a loosely typed language. As such, the way and manner in which it treats logical operations differs from that of other standard languages like Java and C++. JavaScript uses a concept known as "type coercion" to determine the value of a logical operation and always returns the value of the first true type. For instance, take a look at the code below:

var x = mystuff || document; // after execution of the line above, x = document 

This is because mystuff is an a priori undefined entity which will always evaluate to false when tested and as such, JavaScript skips this and tests the next entity for a true value. Since the document object is known to JavaScript, it returns a true value and JavaScript returns this object.

If you wanted a boolean value returned to you, you would have to pass your logical condition statement to a function like so:

var condition1 = mystuff || document; function returnBool(cond){ if(typeof(cond) != 'boolean'){ //the condition type will return 'object' in this case return new Boolean(cond).valueOf(); }else{ return; } } // Then we test... var condition2 = returnBool(condition1); window.console.log(typeof(condition2)); // outputs 'boolean' 

1 Comment

!!condition1 is a much simpler way of getting a boolean true or false from a truthy or falsy result.
2

We can refer to the spec(11.11) of JS here of:

Semantics

The production LogicalANDExpression :LogicalANDExpression &&BitwiseORExpression is evaluated as follows:

  1. Evaluate LogicalANDExpression.

2.Call GetValue(Result(1)).

3.Call ToBoolean(Result(2)).

4.If Result(3) is false, return Result(2).

5.Evaluate BitwiseORExpression.

6.Call GetValue(Result(5)).

7.Return Result(6).

see here for the spec

Comments

1

First, it has to be true to return, so if you are testing for truthfulness then it makes no difference

Second, it lets you do assignments along the lines of:

function bar(foo) { foo = foo || "default value"; 

Comments

1

Compare:

var prop; if (obj.value) {prop=obj.value;} else prop=0; 

with:

var prop=obj.value||0; 

Returning a truthy expression - rather than just true or false - usually makes your code shorter and still readable. This is very common for ||, not so much for &&.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.