开发者

Hide method from enumeration

I want to add a method to every object.

When I just set Object.prototype.somefunction = ..., it will come up when somebody enumerates the object using the usual pattern:

for (i in o){
    if (o.hasOwnProperty(i)){
        // do something with object
    }
}

I tried to set it higher up the prototype chain, but that is not possible (at least not possible in Chrome):

TypeError: Cannot set property 'blah' of undefined

Can I set some flag or something on the method so that it won't get enumerated, just like the native met开发者_开发问答hods won't? (Or at least make hasOwnProperty() return false.)


Update: Sorry, I didn't look at it properly. I am using the ExtJS Framework and the object I was looking at had been processed by Ext.apply() which does the following:

for(var p in c){
    o[p] = c[p];
}

That's where the "own property" flag gets lost.

So I guess I have no chance (in ECMAScript < 5) to inject a method into all objects that behaves like a native one?


I'm not sure I understand correctly. hasOwnProperty is needed exactly for this case, and enumerating an object via

for (i in o){
    if (o.hasOwnProperty(i)){
        // do something with object
    }
}

should not include methods from Object.prototype. Can you please make a working example where you see this behaviour?

I also do not understand what you mean by

I tried to set it higher up the prototype chain

as Object.prototype is the root of the chain, so you cannot get any higher.

In short, the solution is doing exactly what you claim you have done. If this does not work, probably you have made a mistake or found a bug.


I'm not sure what you mean. If a method/property is attached to the prototype, hasOwnProperty will return false. See this code:

function Con(){this.enumerableProp = true;};
Con.prototype.fun = function(){return 'that\'s funny'};

var fun = new Con;

alert(fun.hasOwnProperty('fun')); //=> false
alert(fun.hasOwnProperty('enumerableProp')); //=> true

So, what do you mean?


Make a base class and make all other classes extend it. Add the method to the base class.


ES5 has Object.getOwnPropertyNames() for this:

Object.prototype.lolwat = 42;
var obj = {
  'foo': 1,
  'bar': 2
}; 
Object.getOwnPropertyNames(obj); // ['bar', 'foo']

To see where it is supported: http://kangax.github.com/es5-compat-table/

However, for-in combined with a hasOwnProperty check should work too.


You get that error because there is nothing higher up the prototype chain.

Of note also is that adding to Object's prototype is not really recommended unless absolutely necessary for some reason

Edit: actually, my original answer was incorrect - as the others have pointed out, your object should not have that as own property if it's in Object's prototype.

In any case, if you want to create a prototype chain (or more importantly, avoid changing Object's prototype), you'll want to create your own class:

function MyBaseClass(){
}
MyBaseClass.prototype = new Object();
MyBaseClass.prototype.someMethod = function() { /* your method */ };

var o = new MyBaseClass();
o.hasOwnProperty('someMethod') //should be false
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜