I want to define helper methods on the Array.prototype and Object.prototype. My current plan is to do something like:
Array.prototype.find = function(testFun) {
// code to find element in array
};
So that I can do this:
var arr = [1, 2, 3];
var found = arr.find(function(el) { return el > 2; });
It works fine but if I loop over the array in a for in
loop the methods appear as values:
for (var prop in arr) { console.log(prop); }
// prints out:
// 1
// 2
// 3
// find
This will screw up anybody else relying on the for in
to just show values (especially on Objects). The later versions of javascript have .map and .filter functions built into arrays but those don't show up on for in
loops. How can I create more methods like that which won't show up in a for in
loop?
The Object. setPrototypeOf() method sets the prototype (i.e., the internal [[Prototype]] property) of a specified object to another object or null. All JavaScript objects inherit properties and methods from a prototype. It is generally considered the proper way to set the prototype of an object.
prototype is a property of a Function object. It is the prototype of objects constructed by that function. __proto__ is an internal property of an object, pointing to its prototype. Current standards provide an equivalent Object.
The solution is to create an object without a prototype: var dict = Object. create(null); Such an object is a better map (dictionary) than a normal object, which is why this pattern is sometimes called the dict pattern (“dict” for “dictionary”).
prototype allows you to add new properties and methods to arrays. prototype is a property available with all JavaScript objects.
It's quite easy: Don't use for-in loops with Arrays. Blame everybody else who does so - here is a nice snippet to tell them during development.
Of course, if one does an enumeration in a generic function and doesn't know whether he gets an array, a plain object or an object with a custom prototype, you can use hasOwnProperty
like this:
for (var prop in anyObj )
if (Object.prototype.hasOwnProperty.call(anyObj, prop))
// do something
Notice the explicit use of Object.prototype
to get the function - there might be objects that overwrite it (especially in data-maps, the value might not even be a function), objects that do not support it or objects that do not inherit from Object.prototype at all. See also here.
Yet, only a script author who is aware of the problem would filter all his for-in-loops - and some only do it because it gets recommended - and does it mostly wrong, he should have used a for-loop array iteration instead. But our problem are those authors who do not know of it.
An interesting, but Mozilla-only approach would be overwriting the behavior of enumerations on arrays via __iterate__
, as demonstrated here.
Fortunately, EcmaScript 5.1 allows us setting properties to be non-enumerable. Of course, this is not supported in older browsers, but why bother? We'd need to use es5-shims anyway for all the cool higher-order array stuff :-) Use defineProperty
like this:
Object.defineProperty(Array.prototype, "find", {
enumerable: false,
writable: true,
value: function(testFun) {
// code to find element in array
}
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With