Javascript Custom Array.prototype interferes with for-in loops
I was trying to extend the type of a Javascript object with a function that fetches all the property names that are part of that object (basically what a PHP function does array_keys()
for associative arrays).
Object.prototype.keys = function() {
var a = [];
for (var property in this) {
a.push(property);
}
return a;
};
var a = {a:1,b:2,c:3,d:4};
alert(a.toSource());
var b = a.keys();
alert(b.toSource());
When the variable was checked b
I expected to see ["a","b","c","d"]
, I see instead ["a","b","c","d","keys"]
.
The for-in seems to include prototyped functions keys()
.
Is it possible to avoid this behavior while it is still prototyping, or should I just avoid prototyping?
source to share
Ah - the joys of expanding built-in modules. for..in
checks the entire prototype chain of a repeating object.
What you need (and I believe it is de facto now) is a check with hasOwnProperty
in your loop:
for (var property in this) {
if (this.hasOwnProperty(property)) {
a.push(property);
}
}
hasOwnProperty
ensures that you only get properties that are directly defined on your object (i.e. not up the prototype chain).
source to share
In most situations, you should avoid extending native Object.prototype
. When you expand it, objects ALL get these new properties.
Looping through the properties of an object is a really common task, and as you've noticed, you've encountered unexpected behavior.
I haven't seen many people always use a function hasOwnProperty
in their code, I would say that in "controlled environments", perhaps as a solo developer working on a project, you can manage these issues, but when things get bigger and you have more developers involved, this can cause many problems.
How do I make a static function for Object?
Object.keys = function(obj) {
var a = [];
for (var property in obj) {
if (obj.hasOwnProperty(property)) {
a.push(property);
}
}
return a;
};
var a = {a:1,b:2,c:3,d:4};
alert(a.toSource());
var b = Object.keys(a);
alert(b.toSource());
source to share