Update:
This kind of implementation is simply bad, and I've removed that answer.
I just answered this question. The OP asked for the solution of a private member which can only be accessible by prototype methods. For my answer, I would not suggest to do that but propose the code of its possibility. (And sorry, I do not have a good idea with the title .. )
Code
function A(prop1) {
var myFunc=A.prototype.myFunc;
var that=this;
A.prototype.myFunc=function () {
if (this===that) {
alert(prop1); // do something
}
else {
myFunc.call(this);
}
};
this.retire=function () {
that=undefined;
};
}
A.prototype.myFunc=function () {
};
var a1=new A(1);
var a2=new A(2);
var a3=new A(3);
a1.myFunc();
a2.myFunc();
a3.myFunc();
a2.retire();
a1.myFunc();
a2.myFunc();
a3.myFunc();
// ..
As we can see if any other prototype methods would access prop1, will need to repeat this pattern. I've ever thought about to use a private array to achieve it, but this code seems significantly shorter.
But there are things not good:
It needs an extra function to ensure that not reference to this.
A.prototype.myFunc is growing up(deeper) with the object creation afterwards.
As every var myFunc are still referenced by A.prototype.myFunc, there's a doubt even after invoked retire and clean up all outter reference to an object, it might still alive when the gc comes.
I have limited testing environment and be pleasure to know if there's potential risk with this implementation.
So I think an answer to the question could be:
A. A more feasible approach to alter the prototype methods in the constructor to achieve that the private members can only be accessible in prototype methods.
B. Another method to achieve the same thing, and the code is as simple as possible.
It would also be greatly appreciated to point out my misunderstanding of the closures and the garbage collection within your answers.
Let's see the requirements of the OP in the other question:
Is there a JavaScript pattern which mimics "Protected" object
properties
Answer: sort of, best way (in my opinion) name them _myPrivate
BTW - I do not want the pattern of privileged member functions
accessing private properties since the member function is still
public.
That just makes no sense at all, does the OP think that A.prototype.myFunc is not publicly accessible on A instances?
An introduction to prototype and constructor functions (plus some patterns for privates) can be found here
1 . It needs an extra function to ensure that not reference to this.
There isn't a workaround. that is captured by A.prototype.myFunc within each instantiation, and the instance itself is the object which can access that directly, more objects involve would just make things worse; the retire method is already the simplest way to untangle the reference.
2 . A.prototype.myFunc is growing up(deeper) with the object creation afterwards.
This is just the potential risk. A.prototype.myFunc is made similar to a recursive method, but in fact it isn't. It calls to the previous myFunc and check the instance for its identity. For a few instances it isn't a problem, but for a plenty of the instances, the growing depth will finally cause stack overflow.
As the implementation will whatever need a mechanism for cleanning up, to make the calls deeper gains nothing than just use an array to hold the references, and to clean up on-demand.
3 . As every var myFunc are still referenced by A.prototype.myFunc, there's a doubt even after invoked retire and clean up all outter reference to an object, it might still alive when the gc comes.
The fact is var myFunc which is captured by A.prototype.myFunc will still alive even when the gc comes to collect garbages. There is almost impossible to make the reference to myFunc be released, since it's a chained invocation, the contexts of a deeper call and the shallow call do not have the visibility to each other, thus none of them are able to modify the chain of invocation for skipping a level; unset myFunc would just break the chain. Any trick trying to solve this would involve more objects, that may either increase the cost or being an overkill.
4 . I have limited testing environment and be pleasure to know if there's potential risk with this implementation.
As the answer to the bullet point 2, it may cause stack overflowing when a lot of object are created with it.
I tend to agree with people that say "just don't bother with private," but I think the best way to do this, if you really want it, is with Function#bind. The Crockford article doesn't mention this approach, possibly because it predates bind, and emulating bind with apply gets kind of hairy (or possibly because it's an extra bit of overhead for not much gain).
function classify(fn) {
var privateScope = {}, publicScope = {};
function bindProp(to, target, src, key) {
if (!src.hasOwnProperty(key)) return;
if (!(src[key] && src[key].bind)) return;
target[key] = src[key].bind(to);
}
function ctor() {
var instancePublic = {}, instancePrivate = Object.create(instancePublic);
for (var key in publicScope) {
bindProp(instancePrivate, instancePublic, publicScope, key);
}
for (var key in privateScope) {
instancePrivate[key] = privateScope[key];
}
if (publicScope.hasOwnProperty('constructor'))
publicScope.constructor.apply(instancePrivate, arguments);
return instancePublic;
}
fn.call(publicScope, publicScope, privateScope);
return ctor;
}
This function lets you define a pseudoclass with a "public" and "private" scope. The idea is that:
The public scope object is placed in the prototype chain of the private scope object.
All functions are bound to the private scope object.
First attempt
function classify(fn) {
var privateScope = {}, publicScope = {};
function bindProp(privateScope, scopeObject, key) {
if (!scopeObject.hasOwnProperty(key)) return true;
if (!(scopeObject[key] && scopeObject[key].bind)) return;
privateScope[key] = scopeObject[key].bind(privateScope);
}
function ctor() {
var instancePrivate = Object.create(privateScope),
instancePublic = Object.create(instancePrivate);
for (var key in publicScope) {
console.log(key);
bindProp(instancePrivate, publicScope, key);
}
for (var key in privateScope) {
if (!bindProp(instancePrivate, privateScope, key)
&& !publicScope.hasOwnProperty(key))
instancePublic[key] = void 0;
}
if (publicScope.hasOwnProperty('constructor'))
publicScope.constructor.apply(instancePrivate, arguments);
return instancePublic;
}
fn(publicScope, privateScope);
return ctor;
}
This version had the prototype chain reversed:
The private scope object is placed in the prototype chain of the public scope object.
All functions are bound to the private scope object.
Any private member that's not shadowed by a public member is shadowed by undefined.
Usage
You'd use it something like this:
var Foo = classify(function(pub, priv) {
// constructors are supported but not required
pub.constructor = function(a, b) {
this.a = a;
this.b = b;
};
priv.somePrivateProp = "lol";
priv.doPrivateStuff = function(x, y) {
return x + y;
};
pub.somePublicProp = "rofl";
pub.doStuff = function(x, y) {
return this.doPrivateStuff(x + 1, y + 1) + ' ' + this.somePrivateProp;
};
});
You can play around with this in the console and see that it works like you'd probably expect.
var foo = new Foo('abc', 123);
foo.doStuff(3, 5); // "10 lol"
foo.doPrivateStuff(3, 5) // throws TypeError
Related
Sometimes techniques like this is used to keep variable reference or create singleton. In this way we will call createVariable one time only.
What are the pros and cons of this approach?
function createVariable() {
// usually here may be some long asynchronous task
//
return true;
}
function useVariable() {
if(!useVariable.someVar) {
useVariable.someVar = createVariable();
}
// do something with useVariable.someVar
}
// we will call useVariable several times.
// The idea is to call createVariable
// one time only.
useVariable();
useVariable();
useVariable();
I am grateful to all ideas and recommendations. I don't want to create a singleton. Just want to keep variable reference on function level. Without
pollute the global scope.
What are the pros and cons of this approach?
The approach is okay, although I question the need for it as higher-level design question.
The implementation has a couple of issues:
If someVar contains a falsey value, you'll recreate it when you shouldn't. To check if you've previously created it, use if(!useVariable.hasOwnProperty("someVar")) { rather than if(!useVariable.someVar) {.
The falsey values are 0, "", NaN, undefined, null, and of course, false. (All other values are "truthy".)
Functions have some built-in properties, both their own (name, length) and ones they get from their prototypes (various methods, mostly). So if your variables have names like name, length, call, and so on, you'll mistakenly think you've created them when you haven't as createVariable will already have those properties with truthy values (in your createVariable case). You can work around that by adding a prefix of some kind, or using a separate object as a map (although objects inherit properties, too, so you'd still probably need a prefix), or if you were using ES2015+, you could use a Map.
You've said you only want to create the variable once and "not pollute the global scope" (which is a good thing to avoid). I do that by just wrapping my code in a scoping function:
(function() {
var someVar = createSomeVar();
// My other code here
})();
That keeps the global namespace untouched, and creates only a single copy of someVar without the need for any particular plumbing.
Here is how you would create a singleton (from http://www.dofactory.com/javascript/singleton-design-pattern):
var Singleton = (function () {
var instance;
function createInstance() {
var object = new Object("I am the instance");
return object;
}
return {
getInstance: function () {
if (!instance) {
instance = createInstance();
}
return instance;
}
};
})();
then use it like this
var instance1 = Singleton.getInstance();
var instance2 = Singleton.getInstance();
//You can see here that they are indeed the same instance
alert("Same instance? " + (instance1 === instance2));
NOTE: this took five seconds to find via Google: http://dofactory.com/javascript/singleton-design-pattern
Below I've got a simple little inheritance chain in JavaScript:
var Base =(function(){
function Base(config){
this.name = function(){
return config.name;
}
this.department = function(){
return config.department;
}
}
Base.prototype.calculate = function(){
return this.name().length + this.department().length;
}
return Base;
})();
var base = new Base({
name: 'me',
department: 'this one'
});
console.log(base.calculate());
//inheritance
var Concrete = (function(){
Concrete.prototype = Base.prototype;
function Concrete(config){
Base.apply(this,arguments);
this.number = function(){
return config.number;
}
}
return Concrete;
})();
var concrete = new Concrete({
name: 'concrete',
department: 'the best',
number: 3
});
console.log(concrete.number()); //3
console.log(concrete.name()); //concrete
and it works as expected. I'm curious, though about how correct it would be to place method properties on the prototype of an object. Canonically I know that instance data should go with the instance of the class and the methods the object actually uses should be on the prototype, but what about the situation where the properties themselves are methods (like name and department in Base in this example)? In the interest of keeping things immutable I'd rather not let users change the properties of one of these objects after they've been initialized. In this case does it make any sense to use the prototype instead of the constructor to add functionality to an object?
Or it is only correct to place properties in the constructor so you have access to them when you do something like Base.prototype.whatever?
what about the situation where the properties themselves are methods? In the interest of keeping things immutable I'd rather not let users change the properties of one of these objects after they've been initialized.
I wouldn't call these "properties" any more, but "accessor" or "getter" methods.
In this case does it make any sense to use the prototype instead of the constructor to add functionality to an object?
Yes, if you mean functionality like calculate. If you mean getters like name, department or number you need to place them in the constructor as they need privileged access to the config.
Canonically I know that instance data should go with the instance of the class and the methods the object actually uses should be on the prototype
It's a bit different actually:
Everything instance-specific (data, accessor methods with distinct scopes) needs to go on the instance and is usually set up in the constructor
Everything that is shared amongst all instances (typically methods, but also data in some rare cases) should go on the prototype.
Concrete.prototype = Base.prototype;
No! Use Concrete.prototype = Object.create(Base.prototype); instead.
The heading of your question is a bit misleading.
A direct answer to your heading - Yes, prototype properties are encouraged. They might not make a lot of difference wrt writing the code and the usage of the code, but internally, how JS manages things, like memory, accessing the variables inside closures etc it much better when done via prototype properties.
Now your actual question, is hiding immutable configurations using closures and private scoped variables the only way to do things ?
Right now - I think yes, as ES6 is still not supported completely by every browser yet.
But soon, the support will spread out in all release version of browsers and then you can use this nifty ES6 data type WeakMap . Just like a Map but here the keys are objects. So your Base definition can be written like:
var Base = (function() {
var properties = new WeakMap(); // You have to keep variable private
function Base(config) {
properties.set(this, config);
}
Base.prototype = {
name: function() {
return properties.get(this).name;
},
department: function() {
return properties.get(this).department;
},
calculate: function() {
return this.name().length + this.department().length;
}
};
return Base;
})();
Yes, you still need to keep the variable properties out of reach, so the outer closure. But the number of closures have decreased by 1 in this case.
Similar approach can be for ES6 Symbol but the outer closure will still be required.
What we truly need here are classes which will truly solve the issue, as explained in this very well written blog
I have wondered for a couple years now what people think of doing inheritance with a module-pattern-esque constructor pattern and WITHOUT normal prototypal inheritance. Why do programmers not use a module pattern for non-singleton js classes? For me the advantages are:
Very clear public and private scope (easy to understand the code and the api)
No needing to track the 'this' pointer via $.proxy(fn, this) in callbacks
No more var that = this, etc. with event handlers, etc. Whenever I see a 'this', I know it is context that is being passed into a callback, it is NOT something I am tracking to know my object instance.
Disadvantages:
Small perf degradation
Risk possible "wag of the finger" from Doug Crockford?
Consider this (just run in any js console)
var Animal = function () {
var publicApi = {
Name: 'Generic',
IsAnimal: true,
AnimalHello: animalHello,
GetHelloCount:getHelloCount
};
var helloCount = 0;
function animalHello() {
helloCount++;
console.log(publicApi.Name + ' says hello (animalHello)');
}
function getHelloCount(callback) {
callback.call(helloCount);
}
return publicApi;
};
var Sheep = function (name) {
var publicApi = {
Name: name || 'Woolie',
IsSheep: true,
SheepHello: sheepHello
};
function sheepHello() {
publicApi.AnimalHello();
publicApi.GetHelloCount(function() {
console.log('i (' + publicApi.Name + ') have said hello ' + this + ' times (sheepHello anon callback)');
});
}
publicApi = $.extend(new Animal(), publicApi);
return publicApi;
};
var sheepie = new Sheep('Sheepie');
var lambie = new Sheep('Lambie');
sheepie.AnimalHello();
sheepie.SheepHello();
lambie.SheepHello();
My question is what are the drawbacks to this approach that I am not seeing? Is this a good approach?
Thanks!
[update]
Thanks for the great responses. Wish I could give everyone the bounty. It was what I was looking for. Basically what I thought. I would never use module pattern to construct more than a few instances of something. Usually only a couple. The reason I think it has its advantages is whatever small perf degradation you see is recaptured in the simplicity of the coding experience. We have a LOT of code to write these days. We also have to reuse other peoples' code and personally I appreciate when someone has taken the time to create a nice elegant pattern rather than dogmatically adhering to prototypal inheritance when it makes sense.
I think it boils down to the issue of performance. You mentioned that there is small performance degradation, but this really depends on scale of the application(2 sheep vs 1000 sheep). Prototypal inheritance should not be ignored and we can create an effective module pattern using a mix of functional and prototypal inheritance.
As mentioned in the post JS - Why use Prototype?,
one of the beauties of prototype is that you only need to initialize the prototypal members only once,
whereas members within the constructor are created for each instance.
In fact, you can access prototype directly without creating a new object.
Array.prototype.reverse.call([1,2,3,4]);
//=> [4,3,2,1]
function add() {
//convert arguments into array
var arr = Array.prototype.slice.call(arguments),
sum = 0;
for(var i = 0; i < arr.length; i++) {
sum += arr[i];
}
return sum;
}
add(1,2,3,4,5);
//=> 15
In your functions, there is extra overhead to create a completely new
Animal and sheep each time a constructor is invoked. Some members such as Animal.name are created with each instance, but we know
that Animal.name is static so it would be better to instantiate it once. Since your code implies that Animal.name
should be the same across all animals, it is easy to update Animal.name for all instance simply by updating Animal.prototype.name if we moved
it to the prototype.
Consider this
var animals = [];
for(var i = 0; i < 1000; i++) {
animals.push(new Animal());
}
Functional inheritance/Module Pattern
function Animal() {
return {
name : 'Generic',
updateName : function(name) {
this.name = name;
}
}
}
//update all animal names which should be the same
for(var i = 0;i < animals.length; i++) {
animals[i].updateName('NewName'); //1000 invocations !
}
vs. Prototype
Animal.prototype = {
name: 'Generic',
updateName : function(name) {
this.name = name
};
//update all animal names which should be the same
Animal.prototype.updateName('NewName'); //executed only once :)
As shown above with your currently module pattern we lose effeciency in
updating properties that should be in common to all members.
If you are concered about visibility, I would use the same modular method you are currently using to encapsulate private members but also use
priviledged members for accessing these members should they need to be reached. Priviledged members are public members that provide an interface to access private variables. Finally add common members to the prototype.
Of course going this route, you will need to keep track of this.
It is true that in your implementation there is
No needing to track the 'this' pointer via $.proxy(fn, this) in callbacks
No more var that = this, etc. with event handlers, etc. Whenever I see a 'this', I know it is context that is being passed into a callback, it is NOT something I am tracking to know my object instance.
, but you are are creating a very large object each time which will consume more memory in comparison to using some prototypal inheritance.
Event Delegation as Analogy
An analogy to gaining performance by using prototypes is improved performance by using event delegation when manipulating the DOM.Event Delegation in Javascript
Lets say you have a large grocery list.Yum.
<ul ="grocery-list">
<li>Broccoli</li>
<li>Milk</li>
<li>Cheese</li>
<li>Oreos</li>
<li>Carrots</li>
<li>Beef</li>
<li>Chicken</li>
<li>Ice Cream</li>
<li>Pizza</li>
<li>Apple Pie</li>
</ul>
Let's say that you want to log the item you click on.
One implementation would be to attach an event handler to every item(bad), but if our list is very long there will be a lot of events to manage.
var list = document.getElementById('grocery-list'),
groceries = list.getElementsByTagName('LI');
//bad esp. when there are too many list elements
for(var i = 0; i < groceries.length; i++) {
groceries[i].onclick = function() {
console.log(this.innerHTML);
}
}
Another implementation would be to attach one event handler to the parent(good) and have that one parent handle all the clicks.
As you can see this is similar to using a prototype for common functionality and significantly improves performance
//one event handler to manage child elements
list.onclick = function(e) {
var target = e.target || e.srcElement;
if(target.tagName = 'LI') {
console.log(target.innerHTML);
}
}
Rewrite using Combination of Functional/Prototypal Inheritance
I think the combination of functional/prototypal inheritance can be written in an easy understandable manner.
I have rewritten your code using the techniques described above.
var Animal = function () {
var helloCount = 0;
var self = this;
//priviledge methods
this.AnimalHello = function() {
helloCount++;
console.log(self.Name + ' says hello (animalHello)');
};
this.GetHelloCount = function (callback) {
callback.call(null, helloCount);
}
};
Animal.prototype = {
Name: 'Generic',
IsAnimal: true
};
var Sheep = function (name) {
var sheep = new Animal();
//use parasitic inheritance to extend sheep
//http://www.crockford.com/javascript/inheritance.html
sheep.Name = name || 'Woolie'
sheep.SheepHello = function() {
this.AnimalHello();
var self = this;
this.GetHelloCount(function(count) {
console.log('i (' + self.Name + ') have said hello ' + count + ' times (sheepHello anon callback)');
});
}
return sheep;
};
Sheep.prototype = new Animal();
Sheep.prototype.isSheep = true;
var sheepie = new Sheep('Sheepie');
var lambie = new Sheep('Lambie');
sheepie.AnimalHello();
sheepie.SheepHello();
lambie.SheepHello();
Conclusion
The takeaway is to use both prototypal and functional inheritance to their advantages both to tackle performance and visibility issues.
Lastly, if you are working on a small JavaScript applications and these performance issues are not a concern,
then your method would be viable approach.
a module-pattern-esque constructor pattern
This is known as parasitic inheritance or functional inheritance.
For me the advantages are:
Very clear public and private scope (easy to understand this code and the api)
The same holds true for the classical constructor pattern. Btw, in your current code it's not super clear whether animalHello and getHelloCount are supposed to be private or not. Defining them right in the exported object literal might be better if you care about that.
No needing to track the 'this' pointer via $.proxy(fn, this) in callbacks
No more var that = this, etc. with event handlers, etc. Whenever I see a 'this', I know it is context that is being passed into a callback, it is NOT something I am tracking to know my object instance.
That's basically the same. You either use a that dereference or binding to solve this problem. And I don't see this as a huge disadvantage, since the situation where you'd use object "methods" directly as callbacks are pretty rare - and apart from the context you often want to feed additional arguments. Btw, you're using a that reference as well in your code, it's called publicApi there.
Why do programmers not use a module pattern for non-singleton js classes?
Now, you've named some disadvantages yourself already. Additionally, you are loosing prototypical inheritance - with all its advantages (simplicity, dynamism, instanceof, …). Of course, there are cases where they don't apply, and your factory function is perfectly fine. It is indeed used in these cases.
publicApi = $.extend(new Animal(), publicApi);
…
… new Sheep('Sheepie');
These parts of your code are a little confusing as well. You are overwriting the variable with a different object here, and it happens in the middle-to-end of your code. It would be better to see this as a "declaration" (you're inheriting the parent properties here!) and put it at the top of your function - right as var publicApi = $.extend(Animal(), {…});
Also, you should not use the new keyword here. You do not use the functions as constructors, and you don't want to create instances that inherit from Animal.prototype (which slows down your execution). Also, it confuses people that might expect prototypical inheritance from that constructor invocation with new. For clarity, you even might rename the functions to makeAnimal and makeSheep.
What would be a comparable approach to this in nodejs?
This design pattern is completely environment-independent. It will work in Node.js just as like as at the client and in every other EcmaScript implementation. Some aspects of it even are language-independent.
With your approach, you wont be able to override functions and call the super function so conveniently.
function foo ()
{
}
foo.prototype.GetValue = function ()
{
return 1;
}
function Bar ()
{
}
Bar.prototype = new foo();
Bar.prototype.GetValue = function ()
{
return 2 + foo.prototype.GetValue.apply(this, arguments);
}
Also, in the prototype approach, you can share data among all the instances of the object.
function foo ()
{
}
//shared data object is shared among all instance of foo.
foo.prototype.sharedData = {
}
var a = new foo();
var b = new foo();
console.log(a.sharedData === b.sharedData); //returns true
a.sharedData.value = 1;
console.log(b.sharedData.value); //returns 1
One more advantage of the prototype approach would be to save memory.
function foo ()
{
}
foo.prototype.GetValue = function ()
{
return 1;
}
var a = new foo();
var b = new foo();
console.log(a.GetValue === b.GetValue); //returns true
Whereas in of your approach,
var a = new Animal();
var b = new Animal();
console.log(a.AnimalHello === b.AnimalHello) //returns false
This means with each new object, a new instance of the functions are created where as it is shared among all objects incase of prototype approach.
This wont make much difference incase of few instances but when large number of instances are created, it would show a considerable difference.
Also, one more powerful feature of prototype would be once all objects are created, you can still change the properties among all objects at once (only if they are not altered after object creation).
function foo ()
{
}
foo.prototype.name = "world";
var a = new foo ();
var b = new foo ();
var c = new foo();
c.name = "bar";
foo.prototype.name = "hello";
console.log(a.name); //returns 'hello'
console.log(b.name); //returns 'hello'
console.log(c.name); //returns 'bar' since has been altered after object creation
Conclusion:
If the above mentioned advantages of the prototype approach are not so useful for your application, your approach would be better.
Are there any important/subtle/significant differences under the hood when choosing to use one of these four patterns over the others? And, are there any differences between the them when "instantiated" via Object.create() vs the new operator?
1) The pattern that CoffeeScript uses when translating "class" definitions:
Animal = (function() {
function Animal(name) {
this.name = name;
}
Animal.prototype.move = function(meters) {
return alert(this.name + (" moved " + meters + "m."));
};
return Animal;
})();
and
2) The pattern that Knockout seems to promote:
var DifferentAnimal = function(name){
var self = this;
self.name = name;
self.move = function(meters){
return alert(this.name + (" moved " + meters + "m."));
};
}
and
3) a similar, simple pattern I've often seen:
var DifferentAnimalWithClosure = function(name){
var name = name;
var move = function(meters){
};
return {name:name, move:move};
}
and
4) The pattern that Backbone promotes:
var OneMoreAnimal= ClassThatAlreadyExists.extend({
name:'',
move:function(){}
});
Update 1: Changed pattern #2 and added pattern #3 in response to Elias' response // minor formatting
Just to be clear: JS doesn't know of classes, just objects and custom, self-defined constructor functions, but that's besides the point.
To answer your question in short: yes, there are some small and even some fairly large differences between the various ways of creating a new object you're posting here.
CoffeeScript:
This is actually the most clear-cut and traditional way to create your own constructor, but it has been "optimized" in the sense that it's been ready set-up to use (optional) closure variables.
Basically, what this code does, is use an IIFE, to wrap both the constructor definition and the proptotype method assignments in their own, private scope, that returns a reference to the new constructor. It's just clean, simple JS, no different from what you might write yourself.
Knockout:
Now this threw me a little, because to me, at least, the snippet you provide looks either like part of a module pattern, or a power constructor. But since you're not using strict mode, omitting the new would still make for dangerous situations, and since the entire function goes trough the trouble of creating a new instance of DifferentAnimal, only to then construct a second object literal, assigning all properties of DifferentAnimal to that secondary object, I'd say you're missing something. Because, truth be told, omitting the last return {}; statement here, would probably make no difference at all. Plus: as you can see, you're declaring a method (move) in what is, in essence, a constructor. This means that every instance will be assigned its own function object move, rather then getting it from the prototype.
In short: have another close look at where you got this snippet from, and double-check if this is the full version, because if it is, I can only see arguments against this.
Using a variable, defined inside the constructor is simply: a closure, suppose your properties have a distinct initial state, determined by some arguments, passed to that constructor:
function MyConstructor(param)
{
var paramInit = param/2;//or something
this.p = paramInit;//this property can change later on, so:
this.reInit = function()
{//this method HAS to be inside constructor, every instance needs its own method
this.p = paramInit;//var paramInit can't, it's local to this scope
};
}
var foo = new MyConstructor(10);
console.log(foo.p);//5
foo.p = 'hi';
console.log(foo.p);//hi
foo.reInit();
console.log(foo.p);//5
console.log(foo.paramInit);//undefined, not available outside object: it's a pseudo-private property
That's all there is too it, really. When you see ppl using var that = this; or something, that's often to create a reference to the main object that is available anywhere, without having to deal with the headaches of this (what does this reference? What should the method do when applied to an object other than the one it was originally intended for? etcetera...)
Backbone:
Here, we're dealing with another case: extending objects (IE: using methods, properties of either an existing "class" (constructor) or a particular instance) is not the same as simply creating an object.
As you well know, JS objects can be assigned new properties at any given time. Those properties can be removed, too. Sometimes, prototype properties can be redefined on the instance itself (masking the prototypal behaviour) etc... So it all depends on what you want the resulting object (the newly created object, that extends the given instance) to look like: do you want it to take all properties from the instance, or do you want both objects to use the same prototype somewhere down the line?
Both of these things can be achieved by using simple JS, too, but they just take a bit more effort to write yourself. However, if you write, for example:
function Animal(name)
{
this.name = name;
}
Animal.prototype.eat= function()
{
console.log(this.name + ' is eating');
};
That could be deemed the equivalent of writing:
var Animal = Object.extend({name:'',eat:function()
{
console.log(this.name + ' is eating');
}});
A lot shorter, but lacking the constructor.
new vs Object.create
Well, that's an easy one: Object.create just is a lot more powerful that new: you can define prototype methods, properties (including weather or not they are enumerable, writeable etc...) right at the time you need to create an object, instead of having to write a constructor and a prototype, or create an object literal and mess around with all those Object.defineProperty lines.
The downsides: Some people still aren't using ECMA5 compliant browsers (IE8 is still not quite dead). In my experience: it does become quite hard to debug sizeable scripts after a while: though I tend to use power-constructors more than I do regular constructors, I still have them defined at the very top of my script, with distinct, clear and quite descriptive names, whereas object-literals are things I just create "on-the-fly". Using Object.create, I noticed I tend to create objects that are really a little too complex to qualify as actual object literals, as though they are object literals:
//fictional example, old:
var createSomething = (function()
{
var internalMethod = function()
{//method for new object
console.log(this.myProperty || '');
};
return function(basedOn)
{
var prop, returnVal= {};
returnVal.myProperty = new Date();
returnVal.getCreated = internalMethod;//<--shared by all instances, thx to closure
if (!basedOn || !(basedOn instanceof Object))
{//no argument, or argument is not an object:
return returnVal;
}
for (prop in basedOn)
{//extend instance, passed as argument
if (basedOn.hasOwnProperty(prop) && prop !== '_extends')
{
returnVal[prop] = basedOn[prop];
}
}
returnVal._extends = basedOn;//<-- ref as sort-of-prototype
return returnVal;
};
}());
Now this is pretty verbose, but I've got my basic constructor ready, and I can use it to extend an existing instance, too. It might seem less verbose to simply write:
var createSomething = Object.create(someObject, {getCreated:function()
{
console.log(this.myProperty);
},
myProperty:new Date()});
But IMO, this makes it harder on you do keep track of what object is created where (mainly because Object.create is an expression, and will not be hoisted.Ah well, that's far from a conclusive argument of course: both have their pro's and con's: I prefer using module patters, closures and power constructors, if you don't that's just fine.
Hope this cleared up a thing or 2 for you.
The first example puts the move function in the prototype which will be shared between all Animal instances.
The second example creates a new move function for every the animal instance.
The third example generates a Animal class with the move function in the prototype similar to the first example but with allot less code.
(In your example the name is also shared between all instances, which you probably don't want)
Putting the function in the prototype makes instantiating Animals faster, and because of the way JIT engines work even the execution of the function is faster.
Just saw some interesting code while doing a typo in coffee-script. I got the following code
var Mamal, mam;
Mamal = (function() {
var __priv_func;
function Mamal() {}
Mamal.prototype.simple_var = 5;
Mamal.prototype.test = function() {
return __priv_func(this);
};
__priv_func = function(instance) {
return alert(instance.simple_var);
};
return Mamal;
})();
mam = new Mamal();
mam.simple_var = 10;
mam.test();
Now I've read alot about the module pattern in javascript and why its a bad thing (takes more memory, longer to create...) but of course the upside is having truly private functions/variables. Wouldn't the above code be a good way to create private functions (this wouldn't work for variables, unless you wanted static private variables) as the function is only created once in the closure?
One of the upsides of the module pattern is also the execution speed of functions as the code doesn't have to look up the prototype chain. Would this theoretically give the same speed improvements?
To highlight the points I was making, because clearly there was more to the question than just the title:
Yes a module pattern is a good and commonly used way to create private (er, local) data (functions or whatever), and export some sort of interface. Since a function is the only way to create variable scope, it's the only way to create private functions.
Because the functions will be shared by all objects created from Mamal, they're not useful for a functional inheritance pattern (references to functional inheritance have been removed from the question).
There's no performance improvement over lookups in the prototype chain, because the prototype chain needs to be traversed anyway just to get to your private functions.
To address specific questions points in the updated post:
"Would this be a good way to do private functions?"
Sure, but that's because having a function nested in another is the only way to scope a function.
"Now I've read alot about the module pattern in javascript and why its a bad thing..."
For a one-time use module, I don't see any issue. Also, any data referenced by variables that are no longer needed after the module function exits is free for garbage collection. This wouldn't be the case if they were global, unless you nullified them.
"...of course the upside is having truly private functions/variables..."
Yes, though some would take exception to the use of the word "private". Probably "local" is a better word.
"...this wouldn't work for variables, unless you wanted static private variables..."
Yes, though again some may take exception to the use of the word "static".
"Wouldn't the above code be a good way to create private functions...as the function is only created once in the closure?"
Yes again, nested functions are the only way to make them "private" or rather local.
But yes, as long as the function only ever needs to access the public properties of the objects (which are accessible to any code that can access the object) and not local variables of the constructor, then you should only create those functions once, whether or not you use a module pattern.
"One of the upsides of the module pattern is also the execution speed of functions as the code doesn't have to look up the prototype chain. Would this theoretically give the same speed improvements?"
No, you haven't exported your private functions directly, but rather the only way to call them is by traversing the prototype chain.
But if you ditched the prototype chain, and added functions as properties directly on the objects created, then you'd have some improvement there.
Here's an example:
Mamal = (function() {
var __priv_func;
function Mamal() {
this.test = __priv_func;
}
Mamal.prototype.simple_var = 5;
__priv_func = function() {
return alert( this.simple_var );
};
return Mamal;
})();
Now you've eliminated the prototype chain in the lookup of the test function, and also the wrapped function call, and you're still reusing the __priv_func.
The only thing left that is prototyped is the simple_var, and you could bring that directly onto the object too, but that'll happen anyway when you try to modify its value, so you might as well leave it there.
Original answer:
If you're talking about a module pattern, where you set up a bunch of code in (typically) an IIFE, then export methods that have access to the variables in the anonymous function, then yes, it's a good approach, and is pretty common.
var MyNamespace = (function () {
// do a bunch of stuff to set up functionality
// without pollution global namespace
var _exports = {};
_exports.aFunction = function() { ... };
_exports.anotherFunction = function() { ... };
return _exports;
})();
MyNamespace.aFunction();
But in your example, I don't see and advantage over a typical constructor, unless you decide to use the module pattern as above.
The way it stands right now, the identical functionality can be accomplished like this without any more global pollution, and without the wrapped function:
var Mamal, mam;
Mamal = function() {};
Mamal.prototype.test = function() {
return console.log(this.simple_var);
};
Mamal.prototype.simple_var = 5;
mam = new Mamal();
mam.simple_var = 10;
mam.test();
" Wouldn't the above code be a good way to create private functions (this wouldn't work for variables, unless you wanted static private variables) as the function is only created once in the closure?"
Given the rewritten code above, the function is still only created once. The prototype object is shared between objects created from the constructor, so it too is only created once.
"One of the upsides of functional inheritance is also the execution speed of functions as the code doesn't have to look up the prototype chain. Would this theoretically give the same speed improvements?"
In your code, the function is called via a function in the prototype chain, so it has that same overhead, plus the overhead of finding the local function in the variable scope and invoking that function as well.
So two lookups and two function invocation instead of one lookup and one invocation.
var Mamal, mam1, mam2;
Mamal = (function() {
//private static method
var __priv_func = function() {
return 1;
};
function Mamal() {
}
Mamal.prototype.get = function() {
return __priv_func();
};
Mamal.prototype.set = function(i) {
__priv_func = function(){
return i;
};
};
return Mamal;
})();
mam1 = new Mamal();
mam2 = new Mamal();
console.log(mam1.get()); //output 1
mam2.set(2);
console.log(mam1.get()); //output 2
The function __priv_func is not only private, but also static. I think it's a good way to get private function if 'static' does not matter.
Below is a way to get private but not static method. It may take more memory, longer to create.......
var Mamal, mam1, mam2;
function Mamal() {
//private attributes
var __priv_func = function() {
return 1;
};
//privileged methods
this.get = function() {
return __priv_func();
};
this.set = function(i) {
__priv_func = function(){
return i;
};
};
}
mam1 = new Mamal();
mam2 = new Mamal();
console.log(mam1.get()); // output 1
console.log(mam2.get()); // output 1
mam2.set(2);
console.log(mam1.get()); // output 1
console.log(mam2.get()); // output 2