JavaScript hasOwnProperty vs typeof

I searched a lot on Google but couldn't find where I was looking:

Benefits of using Object.hasOwnProperty versus testing if property is undefined

jsperf speedtest

How to tell if a JavaScript native object has a Property / Method?

.. and many other sites, but this is not the place I'm looking for. My real question is:

Why hasOwnProperty

can't it find a method in its superclass (prototype)? And why would anyone even use it hasOwnProperty

? It's a lot slower than typeof

that, and it doesn't work if you're working with inheritance.

.. second question:

In this question, Barney answers what you should use if ('property' in objectVar)

to check if a property exists, but does not explain why. Does anyone know why you would use this structure?

var objA = function(){};

objA.prototype.alertMessage = function(){
        return 'Hello A';
};

var objB = function(){
    this.hello = function(){
        return 'hello';
    };
};

// Inheritance
objB.prototype  = Object.create(objA.prototype);
objB.prototype.constructor = objA;

var test = new objB();

if (test.hasOwnProperty("alertMessage")){
    console.log("hasOwnProperty: " + test.alertMessage());
}

if (typeof test.alertMessage === "function"){
    console.log("typeof: " + test.alertMessage());
}

if (test.hasOwnProperty("hello")){
    console.log("hasOwnProperty: " + test.hello());
}

if (typeof test.hello === "function"){
    console.log("typeof: " + test.hello());
}

      

Check out jsFiddle

+3


source to share


1 answer


There are a number of reasons one uses (and in some cases should use) hasOwnProperty

, and why its behavior is:

  • As the name implies, hasOwnProperty

    checks whether the subject on which you are testing , the property with the given name. If it inherited a method / property from another object (its prototype), then the owner of this property is not an object, but its prototype. Hence the object does not have a property of its own called X
  • typeof

    It will work most of the time, but the object might look as follows: var o = {foo: undefined}

    . Using typeof

    on o.foo

    will give of course "undefined"

    , but the object has a property calledfoo

  • Usage if ('properyname' in object)

    is a workaround that combines the best of both worlds: in case o = {foo: undefined};

    it will evaluate to true, without the overhead of finding a method hasOwnPropery

    (which is a property Object.prototype

    ) or calling a function with context bindings and all. It will also find properties on the prototype chain.

So, consider the following examples:

var o = {foo: undefined,
    toString: undefined};//overwrite inherited method
console.log(typeof o.foo);//undefined
console.log(typeof o.toString);//undefined
console.log(o.hasOwnProperty('toString'));//true
delete(o.toString);
console.log(typeof o.toString);//function
if ('valueOf' in o)
    console.log(o.valueOf === Object.prototype.valueOf);//true
if ('foo' in o)
    console.log(o.foo);//undefined

      



Another important note is that your statement about hasOwnProperty

which does not work when dealing with inheritance is simply not true. Every object you use in JS inherits from at least one prototype. It is important to understand, understand and respect this. If you are looping an object, it is a good idea to make sure that you are actually iterating over the properties that belong to the object itself. Hence, it is not uncommon to see:

for (p in obj)
{
    if (obj.hasOwnProperty(p))
        //process property
}

      

This is to avoid using code that iterates over all properties in the prototype chain, possibly dumping the super object.

if (!Object.prototype.hasProperty)
{//dirty check ;-P
    Object.prototype.hasProperty = (function(OP)
    {
        return function(name)
        {
            //typeof for speed: if value is not undefined, return true
            if (typeof this[name] !== 'undefined' || this.hasOwnProperty(name))
                return true;
            if (this === OP)//we've just checked the Object.prototype, found nothing, so return false
                return false;
            return Object.getPrototypeOf(this).hasProperty(name);//check prototype
        };
    }(Object.prototype));//OP is object prototype
}

      

+7


source







All Articles