tags:

views:

7467

answers:

9

So:

x = {'key': 1};
if x.hasOwnProperty('key') {
    //do this
}

Is that the best way to do that?

+3  A: 

Yes it is :) I think you can also do Object.prototype.hasOwnProperty.call(x, 'key') which should also work if x has a property called hasOwnProperty :)

But that tests for own properties. If you want to check if it has an property that may also be inhered you can use typeof x.foo != 'undefined'.

Armin Ronacher
+9  A: 
if (x.key !== undefined)

Armin Ronacher seems to have already beat me to it, but:

Object.prototype.hasOwnProperty = function(property) {
    return this[property] !== undefined;
};

x = {'key': 1};

if (x.hasOwnProperty('key')) {
    alert('have key!');
}

if (!x.hasOwnProperty('bar')) {
    alert('no bar!');
}

A safer, but slower solution, as pointed out by Konrad Rudolph and Armin Ronacher would be:

Object.prototype.hasOwnProperty = function(property) {
    return typeof(this[property]) !== 'undefined'
};
enobrev
A: 

Yes, that is a good way to check, but keep in mind that hasOwnProperty does not check the prototype chain.

Jamie
… which is precisely the point of using it, right?
Konrad Rudolph
A: 

OK, looks like I had the right answer unless if you don't want inherited properties:

if (x.hasOwnProperty('key'))

Here are some other options to include inherited properties:

if (x.key) // quick and dirty but does the same thing as below.

if (x.key !== undefined)
sheats
Caveat x.hasOwnProperty('key') can be true whilst x.key !== undefined is not true.
AnthonyWJones
A: 

if (typeof x.key != "undefined"){

}

Because if (x.key) fails if x.key resolves to false (eg x.key = "").

+3  A: 

@[enobrev], @[sheats], bear in mind that undefined is (unfortunately) not a reserved word in JavaScript. Therefore, someone (someone else, obviously) could have the grand idea of redefining it, breaking your code.

A more robust method is therefore the following:

if (typeof(x.attribute) !== 'undefined')

On the flip side, this method is much more verbose and also slower. :-/

Konrad Rudolph
very good point, thank you sir. (can't upvote for 3 hours)
enobrev
+68  A: 

I'm really confused by the answers that have been given - most of them are just outright incorrect. Of course you can have object properties that have undefined, null, or false values. So simply reducing the property check to typeof this[property] or, even worse, x.key will give you completely misleading results.

It depends on what you're looking for. If you want to know if an object physically contains a property (and it is not coming from somewhere up on the prototype chain) then object.hasOwnProperty is the way to go. All modern browsers support it. (It was missing in older versions of Safari - 2.0.1 and older - but those versions of the browser are rarely used any more.)

If what you're looking for is if an object has a property on it that is iterable (when you iterate over the properties of the object, it will appear) then doing: prop in object will give you your desired effect.

Since using hasOwnProperty is probably what you want, and considering that you may want a fallback method, I present to you the following solution:

var obj = {
    a: undefined,
    b: null,
    c: false
};

// a, b, c all found
for ( var prop in obj ) {
    document.writeln( "Object1: " + prop );
}

function Class(){
    this.a = undefined;
    this.b = null;
    this.c = false;
}

Class.prototype = {
    a: undefined,
    b: true,
    c: true,
    d: true,
    e: true
};

var obj2 = new Class();

// a, b, c, d, e found
for ( var prop in obj2 ) {
    document.writeln( "Object2: " + prop );
}

function hasOwnProperty(obj, prop){
    var proto = obj.__proto__ || obj.constructor.prototype;
    return (prop in obj) &&
        (!(prop in proto) || proto[prop] !== obj[prop]);
}

if ( Object.prototype.hasOwnProperty ) {
    function hasOwnProperty(obj, prop){
        return obj.hasOwnProperty(prop);
    }
}

// a, b, c found in modern browsers
// b, c found in Safari 2.0.1 and older
for ( var prop in obj2 ) {
    if ( hasOwnProperty(obj2, prop) ) {
        document.writeln( "Object2 w/ hasOwn: " + prop );
    }
}

The above is a working, cross-browser, solution to hasOwnProperty, with one caveat: It is unable to distinguish between cases where an identical property is on the prototype and on the instance - it just assumes that it's coming from the prototype. You could shift it to be more lenient or strict, based upon your situation, but at the very least this should be more helpful.

John Resig
color me humbled. I had no idea object.hasOwnProperty already exusted in most browsers. Well done, sir.
enobrev
Stop with your truth, this is the internet.
Alan Storm
I guess this is why you're writing books and we're all working for 50 bucks an hour. ;-)
Andrew Hedges
John, you shouldn't use function declarations in an if() branch. That's not allowed in ECMAScript, and current browsers handle them in very different ways. To conditionally create functions, use function expressions:var hasOwnProperty = function () {...};
Zilk
@Zilk, creating functions conditionally seems to work cross-browser and I can't find why it should not be allowed in the spec. Could you clarify your statement?
Tomas
@Tomas, see [Function expressions vs. Function declarations](http://yura.thinkweb2.com/named-function-expressions/#expr-vs-decl). I adapted Kangax' example to John's code, see [JSBin](http://jsbin.com/iwifi3/edit). In several browsers (at least in current Chrome and Opera), the first function declaration is *always* overwritten by the second, regardless of the condition. Meaning, in the best case, the second function declaration is not accounted for *or* `hasOwnProperty` is supported natively. In the worst case, `hasOwnProperty` is not supported but the second declaration tries to invoke it.
Marcel Korpel
Sorry John, -1 for not providing a safe cross-browser solution, see my comment above. ;)
Marcel Korpel
+1  A: 

Let's cut through some confusion here. First let's simplify by assuming hasOwnProperty already exists, this is true of the vast majority of current browsers in use.

hasOwnProperty returns true if the attribute name that is passed to it has been added to the object. It is entirely independant of the actual value assigned to it which may be exactly undefined

Hence:-

var o = {}
o.x = undefined

var a = o.hasOwnProperty('x')  // a is true
var b = o.x === undefined // b is also true

However:-

var o = {}

var a = o.hasOwnProperty('x')  // a is now false
var b = o.x === undefined // b is still true

The problem is what happens when an object in the prototype chain has an attribute with the value of undefined? hasOwnProperty will be false for it and so will !== undefined yet for..in will still list it in the enumeration.

Bottom line is there is no cross browser way (since IE doesn't expose __prototype__) to determine that a specific identifier has not been attached to an object or anything in its prototype chain.

AnthonyWJones
+1  A: 

I generally just do the quick and dirty

if (x.key)

as I normally don't need to check if the property is from the .prototype or the object itself. I also like existence checks for all kinds of things like

var a = []
// some code to potentially populate the array.

if (a.length) {
   // mind blowing code.
}

or

if (!a.length) {
    // other mind blowing code
}
nickyt