25

Is there any way to make an object return false in javascript?

var obj = new Object();

console.log(!!obj) // prints "true" even if it's empty
David Hellsing
  • 106,495
  • 44
  • 176
  • 212

9 Answers9

27

No. An object that doesn't have any properties assigned is not considered "empty".

The fact that a variable holds an instance of an object is enough to cause javascript to treat the variable as having the value of true when an expression requires a boolean value.

Edit

There are clearly some nuances to be cleared up looking at the other answers here.

null is not an object, it is the distinct lack of an object. The question refers to an Object, that is one that has just been created.

AnthonyWJones
  • 187,081
  • 35
  • 232
  • 306
  • 3
    Note that even `new Boolean(false)` is considered `true`. So no, all objects are true. – Thilo May 19 '16 at 11:53
  • Except HTML's `document.all` ... that object `!!document.all` is `false`. (You can `Object.keys(document.all).length` or `""+document.all` or `document.all instanceof Object` to verify that `document.all` is present.) – Eljay Aug 18 '20 at 12:51
12

As of ES8, no, you cannot make an object evaluates to false in JavaScript.

In the specification, all boolean checks (? ! if etc.) depends on ToBoolean,
which is very, very simple:

  • False if undefined, null, false, zero, NaN, or empty string.
  • True for everything else (Object, Proxy, Symbol, etc.)

If the type of the input is object, the result is true. No question asked. No valueOf, no special case.

There is no way to create a falsy object in JavaScript. Only non-objects can be falsy.

Sometimes you may run into object-like "stuff" that return false. Empty string, for example, are used like an object all the time. document.all is another falsy "object".

These are not real objects, however. They cannot have custom properties, cannot be used as prototype, and does not always behave like an object e.g. typeof or strict equal.

This behaviour is most likely here to stay for backward compatibility.

Sheepy
  • 17,324
  • 4
  • 45
  • 69
  • 1
    Oh, that `document.all` thing is interesting. Although, it seems to be a real object indeed. You *can* add custom properties to it, it *can* be used as prototype and it *behaves* like an object with strict equal. It only pretends to be `undefined` when used with `typeof`, loose equal or `ToBoolean`. Still that probably doesn't help at all unless you're into sacrificing a new `document.implementation.createHTMLDocument().all` whenever you need a falsy object. – Robert Feb 07 '17 at 23:09
  • 1
    @Robert The problem is, such usages are out of spec and browser dependent. IE 11 returns `undefined` for `Object.create( document.all )`, and in other browsers you lost the falsy property. In Firefox 52 you can't assign +ve numeric properties. In short, using native object as falsy object is not supported by es or dom spec, and you risk future browsers breaking your code in a way that can be hard to debug and fix. – Sheepy Feb 08 '17 at 01:03
  • sure. I only said it *can* be used as a prototype. Not even sure if it works in all browsers. But of course the prototype chain isn't involved in checking falsiness, so that doesn't really matter. Interestingly IE11 refuses to display the result of `Object.create(document.all)` in the console, but still `Object.create(document.all).__proto__ === document.all` in my test. Regarding the non-writable properties, well, of course there's a lot of magic behind them and every browser seems to behave differently in this respect. – Robert Feb 08 '17 at 22:54
  • @Robert It's quite interesting. If you use some special objects as prototypes, like `navigator`, you get broken objects that throw weird errors when used. – GregRos Dec 23 '17 at 11:59
5

No. But null will convert to false.

> typeof(null)
"object"
> null instanceof Object
false
> !!null
false

To see if the object contains any properties, use (shamelessly copied from How do I count a JavaScript object's attributes?):

function isEmpty (obj) {
    for (var k in obj) 
       if (obj.hasOwnProperty(k))
           return false;
    return true;
}
Community
  • 1
  • 1
kennytm
  • 510,854
  • 105
  • 1,084
  • 1,005
5

A null "object" (really value) will return false.

var obj = null;

console.log(!!obj);

If you wanted to check if it has no properties, you might try:

var obj = new Object();
var empty = true;
for (var p in obj) {
    if (obj.hasOwnProperty(p)) {
       empty = false;
       break;
    }
}
console.log(empty);
tvanfosson
  • 524,688
  • 99
  • 697
  • 795
3

No.

Not sure why you'd want this, but there is a way you could do something like this but it's kinda hacky...

var obj = {
    toString: function() { return ''; }
};

alert(!! (''+obj));
Jani Hartikainen
  • 42,745
  • 10
  • 68
  • 86
  • 2
    One possible reason: You have code that passes around a boolean. Now you want to change that code so that in the `false` case, it also attaches a reason why the value is false. If you could make something appear to be false for boolean operations, but also attach some extra data to it, then the existing code won't need to change. Unfortunately, it seems this isn't possible. – joeytwiddle Jun 30 '16 at 02:56
2

I think that with the first ! you are casting obj to a boolean and negating its value- resulting in true if obj is null - , and with the second ! negating it again.

Pekka
  • 442,112
  • 142
  • 972
  • 1,088
  • 1
    No, the first `!` casts the object to boolean *then* negate it. The second `!` negates it *again* making the end result equivalent to casting the object to boolean. The asker has no problems in that statement. – kennytm Jan 17 '10 at 14:10
1

We can overwrite Object.prototype.valueOf to make an object appear to be false when it is coerced into a primitive, for example during ==.

However it will not appear to be false when we force it into a boolean using !!, so it doesn't really work in the general case.

var obj = {
    valueOf: function () {
        return false
    }
}

> obj == false
true               // Good, we fooled them!

> !!obj
true               // Not so good, we wanted false here

> Boolean(obj)
true               // Not so good, we wanted false here
joeytwiddle
  • 29,306
  • 13
  • 121
  • 110
1

Object-to-boolean conversions are trivial. All objects (including arrays and functions) convert to true. This is so even for wrapper objects (new Boolean(false)) is an object rather than a primitive value, and so it converts to true.

XPD
  • 1,121
  • 1
  • 13
  • 26
0

In your case

console.log(!obj); will return false.

because an object or an empty object is always a truthy.

Praveen
  • 827
  • 6
  • 14