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.
(Incidentally, I’m surprised that augmenting Object.prototype isn’t
warned/deprecated in ES5 Strict. It seems far easier to get people to
stop augmenting Obj.pro, which is likely to break all kinds of things,
than to get everyone to filter every for..in loop. But, anyway.)
It’s especially unproductive because it works against prototypal
inheritance patterns. e.g.:
---------
var dog = { speak: function() { return "arf!" } };
var beagle = Object.create(dog);
beagle.colors = ["white","black","brown"];
var my_dog = Object.create(beagle);
my_dog.name = "Chip";
---------
Note that filtering via hasOwnProperty() will prevent a for..in
iteration from seeing either "colors" or "speak".
Another example: in YUI, it’s impossible to do this
would-otherwise-be-useful pattern:
---------
var base_config = { width: "600px" };
…
var my_config = Object.create(base_config);
my_config.visible = false;
var widget = new Y.Widget(my_config);
---------
In the example above, YUI will not see the “width” property because YUI
rejects all inherited properties when it iterates through the
configuration hash.
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?
-Felipe Gasper
cPanel, Inc.
_______________________________________________
es-discuss mailing list
es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss