for..in, hasOwnProperty(), and inheritance

David Bruant bruant.d at gmail.com
Tue Nov 8 13:54:54 PST 2011


Le 08/11/2011 08:59, Felipe Gasper a écrit :
> Hi everyone,
>
>     There is a widespread practice of doing this:
>
> ---------
> for (key in obj) {
>     if (obj.hasOwnProperty(key)) { … }
> }
> ---------
>
> The oft-stated purpose for this pattern is to weed out code that comes 
> from Object.prototype. The result, though, is that we prevent 
> iteration through *any* inherited properties, which seems like 
> overkill for handling the original problem.
>
> (...)
>
> So, a solution I am considering for my own work defines two methods:
> Object.gave(giver, key, obj)
> Function.prototype.gave(key,obj)
>
> They do what they look like: Object.gave checks if the “giver” really 
> “gave” the “key”ed value to the “obj”ect. The Function.prototype 
> version does the same but assigns the function’s prototype as “giver”. 
> (The original Object.gave() offloads to the prototype method if called 
> with just two args.)
>
> Thus:
> ------------------
> var HOP = 
> Object.prototype.hasOwnProperty.call.bind(Object.prototype.hasOwnProperty);
> Object.gave = function(giver,key,obj) {
>     if (arguments.length === 2) {
>         Function.prototype.gave.apply(this,arguments);
>     }
>
>     var last_prototype;
>     while ( obj !== giver ) {
>         if (HOP(obj,key) || (obj === last_prototype)) return false;
>         last_prototype = obj;
>         obj = Object.getPrototypeOf(obj);
>     }
>
>     return true;
> };
>
> Function.prototype.gave = function(key,obj) {
>     return Object.gave( this.prototype, key, obj );
> };
> ------------------
>
> Then, we can do:
> --------------
> for (var key in obj) {
>     if (Object.gave(key,obj)) { … }
> }
> --------------
>
> …which will still filter out anything in Object.prototype, but will 
> allow iteration through inherited properties.
>
> This seems to me far more useful in general than the hasOwnProperty() 
> check.
>
> Thoughts?
Specifically regarding not enumerating Object.prototype properties, why 
not make every Object.prototype property non-enumerable at the beginning 
of your program?
-----
for(p in Object.prototype)
     Object.defineProperty(Object.prototype, p, {enumerable:false});
-----
Afterward, for any for..in loop, all properties (own or inherited) of 
your object are enumerated except the Object.prototype ones. It makes 
less properties to iterate over, it removes the .hasOwnProperty or 
Object.gave test.
It only break scripts which rely on and expect Object.prototype 
properties being enumerated in a for..in loop (which I am not sure there 
are many out there)

If you ever care about enumerating Object.prototype properties, 
Object.getOwnPropertyNames is still here.

Of course, I do not cover the case Function.prototype.gave covers.

David


More information about the es-discuss mailing list