20

Take this snippet,

var a = {

}

if(typeof a.c === 'undefined'){
 console.log('inside if');
}
if(a.c === undefined){
 console.log('inside if');
}

Both if results in true. Is there any difference in both statements specific to some browsers?

Also, in my last project I have already used typeof a.c == 'undefined' numerous times to check values in json data.

Now, I know that this is not good way, as some value may be undefined too, so my logic will fail.

I should have used hasOwnProperty .

But I am sure that no value will be undefined , can I use typeof a.c == 'undefined' in place of hasOwnProperty or should I change all my typeof with hasOwnProperty

Léo Léopold Hertz 준영
  • 119,377
  • 159
  • 417
  • 655
Jashwant
  • 26,663
  • 15
  • 65
  • 99
  • Just a comment: here is how I've seen it done too: https://github.com/olegskl/is.js/blob/master/is.js#L79 – Florian Margaine Jun 05 '12 at 10:06
  • Another way to do it: `if (a.c === (function(u) { return u })()) {`... – Martijn Jun 05 '12 at 10:09
  • 1
    Similar question: http://stackoverflow.com/questions/4725603/variable-undefined-vs-typeof-variable-undefined – simon Jun 05 '12 at 10:16
  • @FlorianMargaine, in your link, I see `variable === void 0;` , whats that now ? – Jashwant Jun 05 '12 at 11:10
  • 1
    @Jashwant https://developer.mozilla.org/en/JavaScript/Reference/Operators/Special_Operators/void_Operator `The void operator evaluates the given expression and then returns undefined.` So it evaluates `0` (which means it does nothing) and then it returns `undefined`. – Florian Margaine Jun 05 '12 at 12:15

3 Answers3

30

(UPDATE: You might want to check out this question: variable === undefined vs. typeof variable === "undefined").

In very old browsers (Netscape 2, IIRC, and possibly IE 4 or lower), you couldn’t compare a value with undefined, since that caused an error. In any (semi-) modern browser, however, there’s no reason to check typeof value === 'undefined' instead of value === undefined (except for paranoia that somebody might have redefined the variable undefined).

hasOwnProperty serves a different purpose. It checks if the object has a property with the given name, and not its prototype; i.e. regardless of the inherited properties. If you want to check whether an object contains a certain property, inherited or not, you should use if ('c' in a) {...

But basically, these will probably all work:

if (a.c === undefined) console.log('No c in a!');
if (typeof a.c === 'undefined') console.log('No c in a!');
if (!('c' in a)) console.log('No c in a!');
if (!a.hasOwnProperty('c')) console.log('No c in a!');

The main differences being that:

  • a.c === undefined will produce an unexpected result if someone has done undefined = 'defined' or some such trick;
  • !('c' in a) is not very readable (IMHO)
  • !a.hasOwnProperty('c') will return false if the object a doesn’t contain a property c, but its prototype does.

Personally, I prefer the first since it’s more readable. If you’re paranoid and want to avoid the risk of a redefined undefined, wrap your code in a self-executing anonymous function as follows:

(function (undefined) {
  // in here, 'undefined' is guaranteed to be undefined. :-)

  var a = {

  };

})();
Community
  • 1
  • 1
Martijn
  • 12,254
  • 3
  • 46
  • 58
  • In today's version of Chrome, `foo === undefined` triggers an error. See this answer: http://stackoverflow.com/a/4725697/851498 – Florian Margaine Jun 05 '12 at 10:24
  • Also, for "paranoia", this is why many people use the following trick: `( function( window, document, undefined ) { /* your code */ }( window, document ) );` :-) *Oh, you just edited to add this.* – Florian Margaine Jun 05 '12 at 10:26
  • 1
    @FlorianMargaine: Ah, `foo === undefined` is a good one. It’s an even more compelling argument to use `value === undefined`, though, since it allows you to find undeclared variables, which are a Very Bad Thing™. – Martijn Jun 05 '12 at 10:32
  • They cause an error though, which might not be a good thing™ :-) – Florian Margaine Jun 05 '12 at 10:33
  • @FlorianMargaine: an error that indicates a Bad Thing™ is a Good Thing™, though, isn’t it? ;-) – Martijn Jun 05 '12 at 10:35
  • @FlorianMargaine `foo === undefined` could just as well be written as `window.foo === undefined`, which doesn't trigger an error. Besides, the question dealt with object properties, not global variables. But again, those can be accessed as if they were properties of the window object – Elias Van Ootegem Jun 05 '12 at 10:51
  • @EliasVanOotegem what if it's not a global variable? `(function() { foo === undefined; }())` But yeah, this is nitpicking. – Florian Margaine Jun 05 '12 at 10:54
  • @FlorianMargaine: not nitpicking, I like this kind of stuff. In that case: replace window by a reference to the call object (eg `function test(){console.log(this.testVar === undefined);}`). Works like a charm :) – Elias Van Ootegem Jun 05 '12 at 11:02
  • I am actually wrapping my code in a self executing function, so I can simply do `if(a.c === undefined)`. Right ? But it wont work when the value of `c` is actually `undefined` . Right ? – Jashwant Jun 05 '12 at 11:12
  • @EliasVanOotegem what I meant is that you don't want a global variable. – Florian Margaine Jun 05 '12 at 12:12
  • 1
    @Jashwant: Exactly, and good point! After `a.c = undefined`, then `!('c' in a)` will return `false`, but `a.c === undefined` will return `true`, as will `typeof a.c === 'undefined'`. – Martijn Jun 05 '12 at 12:46
  • @Jashwant: Also, just to be certain: make sure that your self-executing function has one more parameter than it has arguments, and call that extra parameter 'undefined'. – Martijn Jun 05 '12 at 12:49
  • @FlorianMargaine: that's what my comment does, `this.testVar === undefined` is inside a function. If you're using variable names that exist ouside the scope, either refer to the callstack, or drop the `this`-bit, since the most immediate scope prevails, AFAIK – Elias Van Ootegem Jun 05 '12 at 13:06
  • I *love* the guaranteed `undefined`. Great answer, especially considering the overwhelming number of examples in the wild which are either paranoid or 1990's-proof. – max Jul 13 '15 at 01:35
  • Another reason for preferring `a.c===undefined`: in the case that a.c is defined, the next thing I often want to do is look at its value. In that case I'd set a local variable to a.c, compare it to undefined, and then (if it's defined) look at its value, all with only one lookup into a's properties. – Don Hatch Apr 20 '17 at 01:32
  • Note that **in** operator should be used only against objects: it will return a type error if used against, eg, a string. I think this is particulary important in nested objects: if I want to access **object.first.second** property an error will occour if **first** exists but it's not an object. So `if ((object.first !== undefined)&&(object.first.second !== undefined)) => correct` while `if (("first" in object)&&("second" in object.first)) => type error` – BigBother Apr 23 '18 at 13:50
3

If your checking standard objects that are the result of parsing a JSON string, .hasOwnProperty has no obvious benefit. Except, of course, if you or some lib you're using has been messing around with the Object.prototype.

In general, undefined as such can be redefined, but I haven't encountered this myself - nor do I think I will ever do so. It is, however impossible (AFAIK) to mess up the return values of typeof. In that respect, the latter is the safest way to go. I do believe some ancient browsers don't work well with the undefined keyword, too.

In resuming: no need to go and replace every single typeof check. On a personal note: I believe it to be good practice to get in the habit of using .hasOwnProperty, though. Hence I'd suggest that, in cases a property might exist, yet be undefined, .hasOwnPorperty is the safest bet.


In response to your comment: yes, typeof will fit your needs ~95% of the time. .hasOwnProperty will work 99% of times. However, as the name indicates: properties higher up the inheritance chain won't be checked, consider the following example:

Child.prototype = new Parent();
Child.prototype.constructor=Child;//otherwise instance.constructor points to parent

function Parent()
{
    this.foo = 'bar';
}

function Child()
{
    this.bar = 'baz';
}

var kiddo = new Child();
if (kiddo.hasOwnProperty('foo'))
{
    console.log('This code won\'t be executed');
}
if (typeof kiddo.foo !== 'undefined')
{
    console.log('This will, foo is a property of Parent');
}

So if you want to check if a single object has a property, hasOwnProperty is what you need. Especially if you're going to change the value of that property (if it's a prototype property, all instances can be altered).
If you want to know if a property has a value (other then undefined), regardless of where it is situated in the inheritance chain, you'll need typeof. I've got a recursive function somewhere to determine where the property can be found in the inheritance chain. Once I've found it, I'll post it here, too.

Update:

As promised, the function to locate a property in an inheritance chain. It's not the actual function I used a while back, so I put together a working draft. It's not perfect, but it could well help you on your way:

function locateProperty(obj,prop,recursion)
{
    recursion = recursion || false;
    var current = obj.constructor.toString().match(/function\s+(.+?)\s*\(/m)[1];
    if (!(obj.hasOwnProperty(prop)))
    {
        if (current === 'Function' || recursion === current)
        {
            return false;
        }
        return locateProperty(new window[current](),prop,current);
    }
    return current;
}
//using the object kiddo
locateProperty(kiddo,'foo');//returns 'Parent'
locateProperty(kiddo,'bar');//returns 'Parent', too

To avoid this last glitch, you could either replace the last return current; statement with return obj;. Or, better still, add the following line to the above snippet:

Child.prototype.constructor=Child;

I forgot that in the first edit...

Elias Van Ootegem
  • 67,812
  • 9
  • 101
  • 138
0
  • Copy the enumerable properties of p to o, and return o.

  • If o and p have a property by the same name, o's property is left alone.

  • This function does not handle getters and setters or copy attributes.

    function merge(o, p) 
    {
        for(prop in p) 
        {   
            // For all props in p.
            if (o.hasOwnProperty[prop]) continue;  // Except those already in o.
            o[prop] = p[prop];                     // Add the property to o.
        }
    
        return o;
    }
    

What is the difference between o.hasOwnProperty[prop] and o.hasOwnProperty(prop) ?

akjoshi
  • 14,589
  • 13
  • 94
  • 116