! operator in JavaScript

I am now confused about ! operator in JavaScript. My understanding was ! operator operates only on boolean. But a comment to one of my answers says it can operate on anything and returns a boolean, which happened to be true after I did some tests.

alert(!undefined); //true
alert(!function(){}); //false
alert(!{}); //false
alert(!null); //true
alert(!()); //crash
alert(!"false"); //false
alert(!false)?;???????????? //true??????????????????

Can somebody help me generalize the behavior of ! operator.

EDIT

Even more confusing stuff:

?alert( new String() == ""); //true
alert(!""); //true
alert(! new String()); //false

How? ?

Answers:

Answer

! does what you think: turns true to false and vice-versa. The weird behavior has to do with how Javascript can convert literally anything to true or false.

http://11heavens.com/falsy-and-truthy-in-javascript

Like in C (only worse) all values can be promoted to true or false. The googlable terms you want are "truthy" and "falsy," or "truthiness" and "falsiness." Truthy means something converts to true, falsy means something converts to false. All values are truthy except null, undefined, 0, "", NaN, and... false

This link has more fun examples:

http://www.sitepoint.com/javascript-truthy-falsy/

And this site really likes doing pathological things with the funny behavior here:

http://wtfjs.com

Also note that == really tries hard to make things comparable whereas === just returns false if the things aren't comparable. Crockford in Javascript: The Good Parts recommends not using == entirely.

Answer

This is not so much a function of ! as a function of what is or is not true in javascript. If you are familiar with casting, the coercing of a variable to a specific type, then the following should be reasonably clear to you.

! only operates on booleans. Therefore, any variable you apply it to that is not boolean is first coerced to be a boolean before applying !. To relate this to your examples:

Boolean(undefined) == false 

undefined is sort of like null in javascript (there are some differences but that's a different topic). It should make sense that the Boolean equivalent is false. undefined goes beyond just absence of value, it declares the variable you are trying to use doesn't even exist.

Boolean(function(){}) == true

Functions are objects in javascript. Even if it's empty, it still has some basic properties common to function objects and therefore its Boolean equivalent is true. It's not nothing so it's something.

Boolean({}) == true

Like an empty function, {} defines an empty object. However, it still has some properties common to objects in javascript. It simply has no custom properties.

Boolean(null) == false

As I mentioned for undefined, null is similar but not quite the same. It indicates the absence of value.

Boolean(()) // error

() on their own don't really mean anything. You need something between them to make the syntax correct so this has no bearing on your false/true question. () alone is simply a syntax error.

Boolean("false") == true

"false" is a string. Just because it contains the letters f,a,l,s,e does not make it the same as the Boolean value false. A non-empty string is something and therefore coerces to the Boolean true. Note strings are kind of special objects in that an empty string "" coerces to false but an empty object, {}, as mentioned, coerces to true.

Boolean(false) == false

This one should be clear. false is already a Boolean so casting it doesn't change its value. It's still false.

From that, you can see how applying ! to each case would give you the results you have seen.

For further reading, here's a pretty good article on type coercion in javascript

UPDATE:

In regards to your String questions. There is a different between a String object and a string literal (something surrounded by quotes). You can create a String object from a string literal but a literal is not automatically an object. The same is true of numbers in javascript. JS has a Number object but you will often define numeric literals. The behaviour of Number is consistent with what you've seen with String:

alert( new Number() == 0); //true
alert(!0); //true
alert(! new Number()); //false

However, as you astutely mentioned in your comment:

alert( new String() === ""); //false

As the types are not the same; object vs. literal.

In general, Boolean(some_object) will always evaluate to true but depending on the exact value, Boolean(some_literal) may evaluate to false.

ADDENDUM

Just because I shot myself in the foot earlier this week I thought this would be a useful piece of information to add. In most languages an empty array, [], will be coerced to false. However, in Javascript, arrays are objects so even the empty array coerces to true. One to watch out for. When switching between js and the various server side languages it's easy to make a slip up along the lines of if(!maybe_empty_array){...} which will never pass because maybe_empty_array will always coerce to true. Instead you should do if(maybe_empty_array.length){...}. If the array is empty its length is 0 which safely coerces to false.

Answer

"Can somebody help me generalize the behavior of ! operator."

Sure. It returns false if its single operand can be converted to true; otherwise, returns true.

Any object (including an "empty" object, {}, or a function), any non-empty string, and any non-zero number can all be converted to true. On the other hand, null, undefined, an empty string and zero will all be converted to false. The ! operator then returns the opposite, hence the results you show in your question.

Answer

! returns false if its single operand can be converted to true, or if it is a non-boolean value:

!(x == y)
!"something" 

And true if its operand can be converted to false:

!(x > y)
Answer

Will be hard to write a more generalized explanation than this:

var arr = [0, "", false, null, undefined, NaN];

for(var i = 0; i < 6; i++){
    console.log(!(arr[i]));//always true
}

Any other values will produce false

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us

©2020 All rights reserved.