Defining methods via prototype vs using this in the constructor - really a performance difference?
See http://jsperf.com/prototype-vs-this
Declaring your methods via the prototype is faster, but whether or not this is relevant is debatable.
If you have a performance bottleneck in your app it is unlikely to be this, unless you happen to be instantiating 10000+ objects on every step of some arbitrary animation, for example.
If performance is a serious concern, and you'd like to micro-optimise, then I would suggest declaring via prototype. Otherwise, just use the pattern that makes most sense to you.
I'll add that, in JavaScript, there is a convention of prefixing properties that are intended to be seen as private with an underscore (e.g. _process()
). Most developers will understand and avoid these properties, unless they're willing to forgo the social contract, but in that case you might as well not cater to them. What I mean to say is that: you probably don't really need true private variables...
Advantages of using prototype, vs defining methods straight in the constructor?
Methods that inherit via the prototype chain can be changed universally for all instances, for example:
function Class () {}
Class.prototype.calc = function (a, b) {
return a + b;
}
// Create 2 instances:
var ins1 = new Class(),
ins2 = new Class();
// Test the calc method:
console.log(ins1.calc(1,1), ins2.calc(1,1));
// -> 2, 2
// Change the prototype method
Class.prototype.calc = function () {
var args = Array.prototype.slice.apply(arguments),
res = 0, c;
while (c = args.shift())
res += c;
return res;
}
// Test the calc method:
console.log(ins1.calc(1,1,1), ins2.calc(1,1,1));
// -> 3, 3
Notice how changing the method applied to both instances? This is because ins1
and ins2
share the same calc()
function. In order to do this with public methods created during construction, you'd have to assign the new method to each instance that has been created, which is an awkward task. This is because ins1
and ins2
would have their own, individually created calc()
functions.
Another side effect of creating methods inside the constructor is poorer performance. Each method has to be created every time the constructor function runs. Methods on the prototype chain are created once and then "inherited" by each instance. On the flip side of the coin, public methods have access to "private" variables, which isn't possible with inherited methods.
As for your function Class() {}
vs var Class = function () {}
question, the former is "hoisted" to the top of the current scope before execution. For the latter, the variable declaration is hoisted, but not the assignment. For example:
// Error, fn is called before the function is assigned!
fn();
var fn = function () { alert("test!"); }
// Works as expected: the fn2 declaration is hoisted above the call
fn2();
function fn2() { alert("test!"); }
Performance wise which is better: An object protype or an constructors native function?
When creating many objects of type DateGreeting
all of them will have a copy of those methods which you have defined on constructor.
While working with that objects you are usually changing their properties, but the methods remain the same.
So declaring methods on prototype would be a more resource-saving approach. Therefore, you can work with many objects which share the same methods without copying methods to each instance.
Declaring methods on custom prototype is definitely better for performance:
// this method will be shared by all DateGreeting instances
DateGreeting.prototype.greeting = function () {
if(this.hours <= 11) {
return "Morning";
} else if (this.hours >= 12 && this.hours <= 17) {
return "Afternoon";
} else {
return "Evening";
}
}
var greeting1 = new DateGreeting(".greet");
var greeting2 = new DateGreeting(".greet");
console.log(greeting1, greeting2);
// the output:
While adding methods to constructor creates copy of each method on each object instance:
function DateGreeting(selector) {
...
this.greeting = function () {
if(this.hours <= 11) {
return "Morning";
} else if (this.hours >= 12 && this.hours <= 17) {
return "Afternoon";
} else {
return "Evening";
}
}
}
var greeting1 = new DateGreeting(".greet");
var greeting2 = new DateGreeting(".greet");
console.log(greeting1, greeting2);
// the output:
Trying to understand the difference between prototype and constructor in JavaScript
It is pretty hard to wrap your mind around this concept if you are used to the ease of extending objects in other OOP languages, but I'll do my best to explain the uses of those and what is what. I am going to assume you are familiar with other OOP languages. Correct me if I'm wrong.
All functions have the prototype Function()
. They are inheriting all base functionality from Function
like toString()
and valueOf()
.
Then there is a constructor. That is what you use to initialize an object with.
p = new Foo();
So in this case we have two things.
- A
function Foo
withFunction
as prototype(Foo) - A
Function
object withFoo()
as constructor(p)
(following me yet?)
The Foo()
constructor can override some base functionality of the Function
constructor or leave it as it is and make good use of it.
If you are familiar with OOP principles, The prototype is the base class, the constructor your current class. In OOP the above would be class Foo extends Function
You can also start inheritance with this entire setup of prototype and constructor making more complex objects as you go whilst sharing functionality.
For example this:
// Make an object initialiser extending Function. In OOP `class Foo extends Function`
function Foo(bar) {
this.baz = bar;
}
Foo.prototype.append = function(what) {
this.baz += " " + what;
};
Foo.prototype.get() {
return this.baz
}
Now lets say we want different ways to get baz
out of there. One for console logging and one for putting it on the title bar.
We could make a big thing about our class Foo
, but we don't do that, because we need to do wholly different things with the new classes that are made for different implementations. The only thing they need to share are the baz
item and the setters and getters.
So we need to extend it to use an OOP term. In OOO this would be the desired end result class Title extends Foo(){}
. So lets take a look at how to get there.
function Title(what) {
this.message = what;
}
At this point the Title
function looks like this:
- prototype Function
- constructor Title
So, to make it extends Foo
we need to change the prototype.
Title.prototype = new Foo();
- prototype Foo
- constructor Foo
This is done by initializing a new Foo()
object against the prototype.
Now its basically a Foo
object called Title
. That is not what we want because now we can't access the message part in Title
.
We can make it properly extend Foo()
by resetting the constructor to Title
Title.prototype.constructor = Title;
- prototype Foo
- Constructor Title
Now we are faced with one more problem. The constructor of Foo
doesn't get initialized so we end up with an undefined this.baz
To resolve that we need to call the parent. In Java you would do that with super(vars)
, in PHP $parent->__construct($vars)
.
In Javascript we have to modify the Title
class constructor to call the constructor of the parent object.
So the Title
class constructor would become
function Title(what) {
Foo.call(this,what);
this.message = what;
}
By using the Function
object property Foo
inherited we can initialize the Foo
object in the Titl
e object.
And now you have a properly inherited object.
So instead of using a keyword like extend
like other OOP languages it uses prototype
and constructor
.
Should we add methods only to the prototypes of our objects?
One reason why one might prefer putting methods on the instance itself would be to ensure the correct this
context while adding a method concisely. Getting this
to work properly is a very common problem in JavaScript.
For example:
class Foo {
i = 0;
clickHandler = () => console.log(this.i++);
}
const f = new Foo();
window.onclick = f.clickHandler;
Difference of methods defined on this in contrast to defined in class body
When you do this.bar = function() { };
in the constructor, you're creating a new function for every instance, and assigning it to the bar
property. This lets the function close over something in the constructor if you want it to. (And if you used an arrow function, the function would close over this
and super
.)
When you declare a method in the class
, you're creating a single function on the prototype object that class will assign to instances, and reusing that function. This lets the function use super
if it needs to access superclass features.
Both have their place depending on what you're doing. You can see that difference here:
class Foo1 {
constructor() {
this.bar = function() {};
}
}
class Foo2 {
bar() {}
}
const f1a = new Foo1();
const f1b = new Foo1();
console.log(f1a.bar === f1b.bar); // false
const f2a = new Foo2();
const f2b = new Foo2();
console.log(f2a.bar === f2b.bar); // true
Javascript prototype operator performance: saves memory, but is it faster?
Edit in 2021:
This question was asked in 2010 when class
was not available in JS. Nowadays, class
has been so optimized that there is no excuse not to use it. If you need to use new
, use class
. But back in 2010 you had two options when binding methods to their object constructors -- one was to bind functions inside the function constructor using this
and the other was to bind them outside the constructor using prototype
. @MarcoDemaio's question has very concise examples. When class
was added to JS, early implementations were close in performance, but usually slower. That's not remotely true anymore. Just use class
. I can think of no reason to use prototype
today.
It was an interesting question, so I ran some very simple tests (I should have restarted my browsers to clear out the memory, but I didn't; take this for what it's worth). It looks like at least on Safari and Firefox, prototype
runs significantly faster [edit: not 20x as stated earlier]. I'm sure a real-world test with fully-featured objects would be a better comparison. The code I ran was this (I ran the tests several times, separately):
var X,Y, x,y, i, intNow;
X = function() {};
X.prototype.message = function(s) { var mymessage = s + "";}
X.prototype.addition = function(i,j) { return (i *2 + j * 2) / 2; }
Y = function() {
this.message = function(s) { var mymessage = s + "";}
this.addition = function(i,j) { return (i *2 + j * 2) / 2; }
};
intNow = (new Date()).getTime();
for (i = 0; i < 10000000; i++) {
y = new Y();
y.message('hi');
y.addition(i,2)
}
console.log((new Date()).getTime() - intNow); //FF=5206ms; Safari=1554
intNow = (new Date()).getTime();
for (i = 0; i < 10000000; i++) {
x = new X();
x.message('hi');
x.addition(i,2)
}
console.log((new Date()).getTime() - intNow);//FF=3894ms;Safari=606
Related Topics
What's the Significant Use of Unary Plus and Minus Operators
How to Fire and Forget a Promise in Nodejs (Es7)
Using "Object.Create" Instead of "New"
Youtube Iframe API: How to Control an Iframe Player That's Already in the HTML
Pass Props to Parent Component in React.Js
Why Was the Arguments.Callee.Caller Property Deprecated in JavaScript
Difference Between Settimeout with and Without Quotes and Parentheses
Allow Google Chrome to Use Xmlhttprequest to Load a Url from a Local File
How to Check If a Checkbox Is Checked
How to Access Iframe Elements with JavaScript
Prevent Execution of Parent Event Handler
Sort Array by Firstname (Alphabetically) in JavaScript
Insert HTML at Caret in a Contenteditable Div
Webdriver Click() VS JavaScript Click()
Determining Image File Size + Dimensions via JavaScript
Stop Execution of JavaScript Function (Client Side) or Tweak It