Reputation: 5281
I'm trying to get my head around the proper way of declaring js functions within my existing custom objects.
E.g. Usually I've done it this way to add functions to my existing object(s):
function whateverController() {
this.doSomething = function() {
}
}
What is the advantage of doing it the following way?
function whateverController() {
...some random code
}
whateverController.prototype.doSomething = function() {
}
From what I've been reading the latter example is the optimum way of declaring these functions to avoid having to recreate these functions every single a time I create a new whateverController object.
Could someone please provide a good use case though where my former example would be better suited? If at all? Any good reading links would be helpful too!
Is the latter method considered standard?
Upvotes: 0
Views: 33
Reputation: 2873
One thing it's useful for is to simulate private methods and members.
JavaScript doesn't come with a way to specify visibility, but there's a way to cheat by using closures. When you run a function, its variables exist inside a closure that lives as long as anything has a reference to it, but they can't be seen by anything outside that closure unless you attach them to something that lives outside. Your code doesn't show it, but you could do something like this:
function whateverController() {
// START OF SCOPE
var privateMember = "secret"; // this acts like a private member.
function privateMethod() {
// This function is private.
// Only other functions declared inside this call can see it.
// But it can see privateMember, and other private stuff, just fine.
}
this.doSomethingPublic = function() {
// This function is public and privileged.
// It can see privateMember and privateMethod, and outside functions can see it.
// This is because you attached it to "this".
}
// END OF SCOPE
}
whateverController.prototype.doSomethingElse = function() {
// This method is public but not privileged.
// It cannot see privateMember or privateMethod,
// because they were declared outside its scope. But it CAN
// see this.doSomethingPublic, because you attached it to this.
}
The downside to this is that private and privileged functions have to be declared inside the constructor. That means they get re-created every time the constructor is run, which is bad for performance. But on the upside, they get to use this trick to create pseudo-private stuff, which things declared on the prototype can't do.
Bottom line: it's better to put your functions on the prototype when you can, but sometimes there are good reasons to pull them into the constructor. It's just not something you should do all the time.
Upvotes: 1
Reputation: 146
To start with, the difference here only really matters if you're not just making singletons--or in other words, all this won't matter much unless you're creating multiple instances of a classes, such as:
var redController = new whateverController();
var blueController = new whateverController();
Now if you are creating multiple instances of an object, putting as much as you can on the class's prototype is the way to go. The reason why is pretty simple. If we do this:
function whateverController() {
this.doSomething = function() {
// TODO - do stuff
}
}
var redController = new whateverController();
var blueController = new whateverController();
var greenController = new whateverController();
redController.doSomething(); // Works fine!
blueController.doSomething(); // Yup, this too!
greenController.doSomething(); // Looking good!
It will work, but at a cost: Every new whateverController()
creates its OWN doSomething
. In other words, you now have three entirely separate doSomething
functions floating around.
Imagine if this class has a dozen functions, and you create a few dozen instances of it? It gets out of hand very quickly.
This is where the prototype version comes in. If we change the code to this:
function whateverController() {
// ...some random code
}
whateverController.prototype.doSomething = function() {
// TODO - do stuff
}
var redController = new whateverController();
var blueController = new whateverController();
var greenController = new whateverController();
redController.doSomething(); // Alright!
blueController.doSomething(); // Still good!
greenController.doSomething(); // ...you get the idea ;)
Now instead of each controller having its own doSomething
, they are using the prototype's doSomething
; they aren't creating a new function every single time! Now if you have a class with a dozen functions, you could create a thousand instances of that class, and you'll still only have those original dozen functions in memory. Far more efficient.
Now, there are instances where you might want to use the first version instead of the prototype version. And the short version for when you'd want to do that is pretty simple: any time that you absolutely require an object to have its own specific version of a function. Generally you don't run into this, but if you start playing around with "private" variables in JavaScript, you'll find you start needing them pretty quickly.
All that said, however, remember that this really only matters if you plan on making multiple instances of an object. If there is only one whateverController
, and only ever will be one, you can choose whichever version pleases you more. After all, if you're not creating new instances of the class, then you won't be creating new instances of the function either.
Oh, and one more thought before I forget: It's generally accepted that class constructors start with a capital letter. In other words, if don't plan on using whateverController
as a singleton, and want to use it to make instances of the class, you should probably name it WhateverController
.
Upvotes: 1