-
-
Save petermichaux/2489714 to your computer and use it in GitHub Desktop.
Function.prototype.new = function() { | |
var obj = Object.create(this.prototype); | |
this.apply(obj, arguments); | |
return obj; | |
}; | |
function Person(name) { | |
this.setName(name); | |
} | |
Person.prototype.getName = function() { | |
return this.name; | |
}; | |
Person.prototype.setName = function(name) { | |
this.name = name; | |
}; | |
var david = Person.new('Dave'); | |
david.getName(); // 'Dave' |
And you don't even need a function for that https://github.com/Gozala/selfish
I would refrain from using Object.create
for creating object instances. I've been there and I started to approach performance issues. Problem is that Object.create
for each call creates temporary function constructor, and that takes efficiency down.
My current practice is to use Object.create
for creating prototypes but not for instances, so e.g.:
function Animal(name) {
this.name = name;
};
Animal.prototype = {
say: function (what) {
console.log(what);
}
}
function Dog(name) {
Animal.call(this, name);
};
// Extend Animal with Object.create
Dog.prototype = Object.create(Animal);
Dog.prototype.say = function () {
Animal.prototype.say.call(this, 'bark');
};
// Create Dog instance with new
var sparky = new Dog('Sparky');
And with that approach, it's hard to come up with sensible Function.prototype.new
implementation, that wouldn't kill performance.
Problem is that Object.create for each call creates temporary function constructor
People commonly write their Object.create polyfill like this which requires the creation of a new constructor each call.
Object.create = function(proto) {
function F() {}
F.prototype = proto;
return new F();
};
but they could write something more efficient to reuse the constructor function:
Object.create = (function(){
function F() {}
return function(proto) {
F.prototype = proto;
return new F();
};
}());
@petermichaux I was actually talking about native implementations, but still reasoning I gave is probably not valid, as specification doesn't imply creation of temporary function constructors. In V8 creating object via Object.create
is significantly slower than using new
construct, and it is noticeable when you work with many objects.
http://jsperf.com/object-create-vs-new-object
It's probably issue of V8 engine that hopefully someday will be fixed (SpiderMonkey that's in Firefox doesn't have that problem).
Nice benchmark: http://jsperf.com/object-create-vs-crockford-vs-jorge-vs-constructor/
So solution you propose for shim instead of using native Object.create
would probably be best fit:
Function.prototype.new = (function() {
function F() {};
return function () {
F.prototype = this.prototype;
var obj = new F();
this.apply(obj, arguments);
return obj;
};
}());
That is not an apples-to-apples perf test because the the constructor function version has the opportunity to initialize the newly created instance. When adding initialize to the Object.create version, the performance of Object.create is not much greater than the constructor version in FF12
http://jsperf.com/object-create-vs-crockford-vs-jorge-vs-constructor/31
@petermichaux I'm not sure what you want to point now.
What's clear to me from any version of this benchmark is that using new
is magnitudes faster than native or shimmed Object.create
version. Exception is just Firefox on which it's pretty same, hopefully Chrome and Safari will have it fixed, at least I don't see any technical reason why it should be so slow there.
You have 2 big issues. Both are related with the built-in constructors and Object.create. Even and every object inherits from Object.prototype, the objects have hidden internal behavior which depends on the type of the objects. e.g arrays have special setter, functions have call and construct methods etc.
Array.new();
Will create a new native object which inherits from Array.prototype but it would not be true array, because the internal behavior is not inherited trough the prototype chain.
The second problem is again with built-ins which have non-generic methods, e.g.:
String(String.new('')); // TypeError: String.prototype.toString is not generic
A better way to implement new
is as follows: https://gist.github.com/aaditmshah/6269739
See the following StackOverflow answer: http://stackoverflow.com/a/17345713/783743
is this not even nicer ?
One could create a utility fn which should be called after constructor definition and will ensure that constructor will be always instantiated.