Robust hasOwnProperty

R

raider5

I recently tried out "My Library" (looks nice), and noticed it doesn't
use hasOwnProperty, instead is uses a custom isOwnProperty function.
I've written an alternative hasOwnProperty function to handle a couple
of edge cases isOwnProperty doesn't:


var hasOwnProperty = (function(hop){
return hop ? function(o,p){
return hop.call(o,p);
}:function(o,p){
var proto = o.constructor.prototype, b = true, t;

if(p in proto){
t = proto[p];
b = (proto[p]=1) !== o[p] || (proto[p]=2) !== o[p];
proto[p] = t;
}

return b;
};
}(Object.prototype.hasOwnProperty));

function testIsOwnProperty(){
this.a=1;
}
testIsOwnProperty.prototype.a=1;
testIsOwnProperty.prototype.b=undefined;

var o = new testIsOwnProperty();

for(var p in o){
if(hasOwnProperty(o,p)){
alert(p+':'+o[p]); //a:1
}
}


I'm curious as to what others have implemented for hasOwnProperty
should it not exist? And if there is an alternative method that is
preferable?
 
R

RobG

I recently tried out "My Library" (looks nice), and noticed it doesn't
use hasOwnProperty, instead is uses a custom isOwnProperty function.
I've written an alternative hasOwnProperty function to handle a couple
of edge cases isOwnProperty doesn't:

Which are?

var hasOwnProperty = (function(hop){
return hop ? function(o,p){
return hop.call(o,p);
}:function(o,p){
var proto = o.constructor.prototype, b = true, t;

if(p in proto){
t = proto[p];
b = (proto[p]=1) !== o[p] || (proto[p]=2) !== o[p];
proto[p] = t;
}

return b;
};

}(Object.prototype.hasOwnProperty));

function testIsOwnProperty(){
this.a=1;}

testIsOwnProperty.prototype.a=1;
testIsOwnProperty.prototype.b=undefined;

var o = new testIsOwnProperty();

for(var p in o){
if(hasOwnProperty(o,p)){
alert(p+':'+o[p]); //a:1
}
}

I'm curious as to what others have implemented for hasOwnProperty
should it not exist? And if there is an alternative method that is
preferable?

It's usually possible to remove the need for hasOwnProperty. It only
seems useful to me when copying properties from one object to another
using a for..in statement and there is a requirement to filter out
inherited enumerable properties. In those cases it can be specified
that only objects created using Object as a constructor or an object
literal should be passed as arguments (and of course that
Object.prototype isn't modified).

A related issue is where properties added to an object have the same
name as non-enumerable properties of Object.prototype (such as
toString and valueOf) and they are ignored by for..in (as happens in
IE). One strategy is something like:

if (obj.toString != Object.prototype.toString) {

/* obj has a toString property that isn't inherited
* from Object.prototype.toString, deal with it
*/
}

Of course that doesn't work if obj.toString is inherited from some
other prototype, such as when working across frames, in more complex
inheritance schemes or if obj is a function or some other type of
object. Perhaps hasOwnProperty can be used here? It would require
testing the list of possible properties that might fail, there is no
way of knowing the full extent of such a list, it can only be
discovered by trial and error and it would make the for..in loop
slower.

To me, if it can't be made bullet-proof, a general solution is doomed.
Better to document the exceptions as they are discovered and either
design away the need or work within known safe limits.
 
G

Garrett Smith

That method is missing from older webkits and using it on global object,
indirectly, has surprising results in Opera.

Where `__proto__` is available it can be used to make a better guess and
I think kangax had a way to determine with certainty using a more
elaborate trick that involved deleting the object's `__proto__`
property, performing a test with `in`, and then restoring `__proto__`.
That required feature tests to determine if `__proto__` was deletable
and then restorable.

[...]
To me, if it can't be made bullet-proof, a general solution is doomed.
Better to document the exceptions as they are discovered and either
design away the need or work within known safe limits.
A strategy which I've gotten away with (so far) is to limit the need for
`hasOwnProperty` and then put my own wrapped `hasOwnProperty` function
inside a closure, for use within that closure only.
 
A

Asen Bozhilov

raider5 wrote:

var hasOwnProperty = (function(hop){
    return hop ? function(o,p){
        return hop.call(o,p);
    }:function(o,p){
        var proto = o.constructor.prototype, b = true, t;

        if(p in proto){
            t = proto[p];
            b = (proto[p]=1) !== o[p] || (proto[p]=2) !== o[p];
            proto[p] = t;

Don't touch my prototypes :) You cannot be sure that property is
exactly at this point of prototype chain. What will be happen if I
have prototype chain like follow:

Foo.prototype:
x : 10
^
Bar.prototype:

var instance = new Bar();
instance.x; //10

hasOwnProperty(instance, 'x'); //false

Foo.prototype.x = 50;
instance.x; //10 Expected result here is 50

So please, do not shadow properties in prototype chain. Your approach
itself needs built-in `hasOwnProperty' :)

        }

        return b;
    };

}(Object.prototype.hasOwnProperty));
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
What is the main goal of this?
 
A

Asen Bozhilov

Garrett said:
Where `__proto__` is available it can be used to make a better guess and
I think kangax had a way to determine with certainty using a more
elaborate trick that involved deleting the object's `__proto__`
property, performing a test with `in`, and then restoring `__proto__`.
That required feature tests to determine if `__proto__` was deletable
and then restorable.

We have discussed that topic. If the `__proto__' is writeable and it's
mimic of internal [[Prototype]] you don't need feature test for
deletable and restorable. You can do:

var obj = {},
proto = obj.__proto__;

//Truncate prototype chain
obj.__proto__ = {__proto__ : null};

//Restore the old state of prototype chain
obj.__proto__ = proto;
 
R

raider5

I recently tried out "My Library" (looks nice), and noticed it doesn't
Which are?

If the object and prototype contain a property with the same name and
value it returns false (expected true). If there is a property on the
prototype with an undefined value and no property on the object with
the same name, it returns true (expected false).

A related issue is where properties added to an object have the same
name as non-enumerable properties of Object.prototype (such as
toString and valueOf) and they are ignored by for..in (as happens in
IE). One strategy is something like:

  if (obj.toString != Object.prototype.toString) {

    /* obj has a toString property that isn't inherited
     * from Object.prototype.toString, deal with it
     */
  }

Yeah that is the first part of the problem, iterating through the
object. I have checks in place for this already, something along the
line of:

var hasDontEnumBug = true;
for(var p in {toString:1}){
hasDontEnumBug = false;
}

If the bug is present manually loop through the non-enumerable
properties:
['toString', 'valueOf', 'toLocaleString', 'hasOwnProperty',
'isPrototypeOf', 'propertyIsEnumerable', 'constructor']
 
R

raider5

Where `__proto__` is available it can be used to make a better guess and
I think kangax had a way to determine with certainty using a more
elaborate trick that involved deleting the object's `__proto__`
property, performing a test with `in`, and then restoring `__proto__`.
That required feature tests to determine if `__proto__` was deletable
and then restorable.

I'll check this out.

A strategy which I've gotten away with (so far) is to limit the need for
`hasOwnProperty` and then put my own wrapped `hasOwnProperty` function
inside a closure, for use within that closure only.

Do you have an example I could take a look at?
 
R

raider5

var hasOwnProperty = (function(hop){
    return hop ? function(o,p){
        return hop.call(o,p);
    }:function(o,p){
        var proto = o.constructor.prototype, b = true, t;
        if(p in proto){
            t = proto[p];
            b = (proto[p]=1) !== o[p] || (proto[p]=2) !== o[p];
            proto[p] = t;

Don't touch my prototypes :) You cannot be sure that property is
exactly at this point of prototype chain. What will be happen if I
have prototype chain like follow:

Foo.prototype:
    x : 10
     ^
Bar.prototype:

var instance = new Bar();
instance.x; //10

hasOwnProperty(instance, 'x'); //false

Foo.prototype.x = 50;
instance.x; //10 Expected result here is 50

So please, do not shadow properties in prototype chain. Your approach
itself needs built-in `hasOwnProperty' :)

I'm a bit confused by what you mean, if the following is what you are
referring to then it seems ok to me, am I missing something?

function Foo(){}
Foo.prototype.x = 10;

function Bar(){}
Bar.prototype = Foo.prototype;

var instance = new Bar();
hasOwnProperty(instance,'x'); //false < the correct result as Bar
doesn't have its own 'x'

Foo.prototype.x = 50;
instance.x; // 50 as expected

    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
What is the main goal of this?

An additional precaution in case the current object has an overridden
hasOwnProperty property.
 
A

Asen Bozhilov

raider5 said:
Yeah that is the first part of the problem, iterating through the
object. I have checks in place for this already, something along the
line of:

var hasDontEnumBug = true;
for(var p in {toString:1}){
    hasDontEnumBug = false;

}

No, this is wrong assumption. If `hasDontEnumBug = false' that mean
object has one or more enumerable properties. With code like this you
cannot be sure that `toString' property has been enumerated. For
example:

Object.prototype.breakHasDontEnumBug = true;

Now try your detection of DontEnum bug.

Better use:

var hasDontEnumBug = !{toString :
true}.propertyIsEnumerable('toString');
 
A

Asen Bozhilov

raider5 said:
I'm a bit confused by what you mean, if the following is what you are
referring to then it seems ok to me, am I missing something?

function Foo(){}
Foo.prototype.x = 10;

function Bar(){}
Bar.prototype = Foo.prototype;

var instance = new Bar();
hasOwnProperty(instance,'x'); //false < the correct result as Bar
doesn't have its own 'x'

Foo.prototype.x = 50;
instance.x; // 50 as expected

No.

function Foo(){}
Foo.prototype.x = 10;

function Bar(){}
Bar.prototype = new Foo();
Bar.prototype.constructor = Bar;

var instance = new Bar();

Test now ;)
 
R

raider5

function Foo(){}
Foo.prototype.x = 10;

function Bar(){}
Bar.prototype = new Foo();
Bar.prototype.constructor = Bar;

var instance = new Bar();

Test now ;)

I'm still not clear on what the test is. Neither of the constructors
have their own properties and the results are as expected, what am I
missing?

function Foo(){}
Foo.prototype.x = 10;

function Bar(){}
Bar.prototype = new Foo();
Bar.prototype.constructor = Bar;

var instance = new Bar();

alert(hasOwnProperty(instance,'x')); //false < the correct result as
Bar doesn't have its own 'x'
Foo.prototype.x = 50;
alert(instance.x); // 50 as expected
 
A

Asen Bozhilov

raider5 said:
I'm still not clear on what the test is. Neither of the constructors
have their own properties and the results are as expected, what am I
missing?

You have tested with built-in `hasOwnProperty'.

var hasOwnProperty = (function(hop){
return function(o,p){
var proto = o.constructor.prototype, b = true, t;

if(p in proto){
t = proto[p];
b = (proto[p]=1) !== o[p] || (proto[p]=2) !== o[p];
proto[p] = t;
}

return b;
};
}(Object.prototype.hasOwnProperty));


function Foo(){}
Foo.prototype.x = 10;

function Bar(){}
Bar.prototype = new Foo();
Bar.prototype.constructor = Bar;

var instance = new Bar();
print(hasOwnProperty(instance, 'x')); //false
Foo.prototype.x = 50;
print(instance.x); //10
 
A

Asen Bozhilov

Asen said:
You have tested with built-in `hasOwnProperty'.

And there is another problem with you `hasOwnProperty' implementation.
If property does not exist in the prototype chain your function
returns `true'.
Try it the follow code:

hasOwnProperty({}, 'foo'); //true

It must returns `false'.
 
R

Ry Nohryb

(...)
I'm curious as to what others have implemented for hasOwnProperty
should it not exist? And if there is an alternative method that is
preferable?

//create a test object
a= {}
//save its prototype
saved= a.__proto__;
//cut the prototype chain
a.__proto__= null;
//test with 'in': it now behaves as a .hasOwnProperty.
"toString" in a
--> false
a.toString= 27
"toString" in a
--> true
//Restore the prototype chain
a.__proto__= savedProto;

The problems: most browsers in which this runs have .hasOwnProperty()
already, and I'd bet this -too- fails in IEs (what doesn't?), and
"__proto__" in a is always going to return true.

What do you need this for ?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,774
Messages
2,569,598
Members
45,145
Latest member
web3PRAgeency
Top