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