Using a Function prototype, that sounds like a non-sense, it is possible to know if a constructor has some property, or method, defined in its prototype.
Function.prototype.prototyped = function(){
for(var i in new this)
return true;
return false;
};
Some test example?
alert(Array.prototyped()); // false
Object.prototype.each = function(){};
alert(Array.prototyped()); // true
delete Object.prototype.each;
alert(Array.prototyped()); // false
Array.prototype.each = function(){};
alert(Array.prototyped()); // true
alert(Object.prototyped()); // false
Update
Has Kangas spotted, there is no reason to create a new instance.
We could loop directly the prototype object.
But what's up if we have injected privileged methods in the constructor?
Array = function(Array){
var prototype = Array.prototype;
return function(){
arguments = prototype.slice.call(arguments, 0);
arguments.each = function(){
prototype.forEach.apply(this, arguments);
};
return arguments;
};
}(Array);
var a = new Array(1, 2, 3);
a.each(function(value){
alert(value)
});
for(i in Array.prototype)
alert(i); // nothing
Above example is the reason I chose to create an instance ... but hey, why on heart someone should wrap a native constructor? :P
Smart!
ReplyDeleteI don't see a reason to instantiate a constructor. We might as well iterate over its prototype:
ReplyDeleteFunction.prototype.prototyped = function(){
for (var prop in this.prototype)
return true;
return false;
}
Best,
kangax
Good point kangax. I have updated the post explaining why I chose the new this, instead of this.prototype.
ReplyDeleteAt the same time, the creation of that "empty instance", should not be a problem for memory leaks.
Anyway, if you want to use prototyped method with every kind of constructor, your solution, as far as I know, is definitively better, while mine, was dedicated to primitive constructor that do not necessary require arguments (Array, Boolean, Date, Function, Number, Object, String)
Regards
Another unfortunate downside to performing an instantiation is if the constructor does work with arguments. Which seems like a reasonable concern if you are performing introspection at runtime.
ReplyDeletePerhaps a try/catch block? Which still won't handle constructors with side effects...
The prototype inspection, while lossy, seems like a safer choice. Especially when modifying a base prototype.
Nice work,
s
following prototypal inheritance, there is no reason to use slow try catch :)
ReplyDeleteFunction.prototype.prototyped = function(){
var i = function(){};
i.prototype = this.prototype;
for(i in new i)
return true;
return false;
};
But above code is exactly the same of kangax one:
Function.prototype.prototyped = function(){
for(var i in this.prototype)
return true;
return false;
};
and I have already explained that I did not look for prototype because:
- the aim is to know if primitive constructors have been prototyped
- someone culd wrap a constructor injecting privileged methods or parameters
;)
Andrea,
ReplyDeleteI understand that it was intended for native constructors (there are no "primitive" constructors afaik :)) but I just don't see a reason to create a new instance of Array, Object, Date, etc. when iterating over their prototype does the same thing. If you frequently call #prototyped (in some loop), then you clobber memory with bunch of unnecessary objects. Yes, they are all being GC'ed right away, but you get the point ;)
I think that "injected privileged methods" is kind of an edge case :), but I see your point. Of course, "new Func" won't have same members as "Func.prototype" if Func explicitly returns an "alien" object (as in your example)
ReplyDelete