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

Reply via email to