While reading other people's source code and various articles over the web, I found that when different people use "object-oriented-style" programming in JavaScript, they often do it quite differently.
Suppose, I want to create a tiny module having 1 property and 1 function. I've seen at least 4 approaches to this task:
// Option 1
var myObject1 = {
myProp: 1,
myFunc: function () { alert("myProp has value " + this.myProp); }
};
// Option 2
var myObject2 = function () {
return {
myProp: 1,
myFunc: function () { alert("myProp has value " + this.myProp); }
};
}();
// Option 3
var MyObject3 = function () {
this.myProp = 1;
this.myFunc = function () { alert("myProp has value " + this.myProp); }
};
var myObject3 = new MyObject3();
// Option 4
var MyObject4 = function () { };
MyObject4.prototype.myProp = 1;
MyObject4.prototype.myFunc = function () { alert("myProp has value " + this.myProp); };
var myObject4 = new MyObject4();
All these approaches are syntactically different but seem to produce objects that can be used in the same way.
What's the semantic difference between them? Are there cases when for some reason I should choose one of these options over all the rest?
myObject1 is an object literal (singleton). Useful in cases where you want to have just one object of this type. Look at it as a static object.
myObject2 returns an object literal. So right after doing var foo = myObject2(), the variable foo will hold the result { myProp: 1, myFunc: function(){...} } with reference to the parent function that has executed. This is called a closure. This can be used to define a public API or modules, for example.
i.e.:
var foo = (function(){
var privateProp = "I am a private property";
// the object below is returned, privateProp is accessible
// only through foo.publicProp
return {
publicProp: privateProp
}
})();
The privateProp property is now accessible through foo.publicProp.
MyObject3 and MyObject4 are constructor functions. By using the new keyword before the function call, you tell JavaScript to create an instance of that object. This means that every new object created this way will inherit properties and methods from the object definition.
The difference between MyObject3 and MyObject4 is that in the case of the former, every instance of that object will have its own copy of the myProp and myFunc properties, whereas the latter will only reference those properties. That means that no matter how many instances of object MyObject4 you create, there will be only one of myProp and myFunc.
I recommend you look up on how closures, prototypal inheritance, and several object design patterns (modules, etc.) work in JavaScript.
Both 1. and 2. are pretty much identical in your example. You could make 2. make an actual difference by declaring "private" variables in the IIFE's scope, like this:
var myObject2 = function () {
var myPrivateProp = ...;
return {
getPrivateProp: function() { return myPrivateProp; }
};
}();
In general, those create a value, not something that you would call a class of values.
Instead, what 3. and 4. are doing is creating a prototype that can be then used to create more usable values out of it. Whether you actually declare the defaults on the prototype or in the constructor doesn't make much difference.
So, to sum up, 1&2 are something like a "lambda" object, without a named prototype, while 3&4 actually make the thing reusable and recreatable.
Related
This question already has answers here:
Use of 'prototype' vs. 'this' in JavaScript?
(15 answers)
Closed 9 years ago.
I am wondering if there are any advantages of using any of these over the other, and which way should I go?
Constructor approach:
var Class = function () {
this.calc = function (a, b) {
return a + b;
};
};
Prototype approach:
var Class = function () {};
Class.prototype.calc = function (a, b) {
return a + b;
};
I don't like that, using the prototype, method definitions are separated from the class, and I'm not aware if there is any specific reason I should use this over just the first approach.
Also, is there any benefit of using a function literal to define a "class", over just function definition:
var Class = function () {};
vs
function Class () {};
Thanks!
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!"); }
The advantage of the prototype approach is efficiency. There is one calc() function object shared between all Class objects (by which I mean objects created by calling the Class constructor). The other way (assigning methods within the constructor) creates a new function object for every Class object, using more memory and taking more processing time when calling the Class constructor. However, this approach does have an advantage: the calc() method has access to local variables within the constructor, which you can use to your advantage:
function Class() {
var calcCallCount = 0;
this.calc = function (a, b) {
++calcCallCount;
alert("Calc called " + calcCallCount + " times");
return a + b;
};
};
Regarding var Class = function() {...} versus function Class() {...}, I generally prefer the latter is because it means the function has a name, which can be useful when debugging. The other difference is that the latter version (a function declaration) is hoisted, meaning that it is available everywhere within the scope in which it is defined, not just after the definition. However, some people prefer to use the former (a function expression) everywhere.
var YourClass = function(){
var privateField = "somevalue";
this.publicField = "somevalue";
this.instanceMethod1 = function(){
//you may access both private and public field from here:
//in order to access public field, you must use "this":
alert(privateField + "; " + this.publicField);
};
}
YourClass.prototype.instanceMethod2 = function(){
//you may access only public field 2 from this method, but not private fields:
alert(this.publicField);
//error: drawaback of prototype methods:
alert(privateField);
};
Advantages of prototype methods:
When you define methods via prototype, they are shared among all YourClass instances. As a result the total size of such instances is < than if you define methods in constructor; There are tests that show how method definition via prototype decrease the total size of html page and as a result a speed of its loading.
another advantage of methods, defined via prototype - is when you use inherited classes, you may override such methods and in the overriden method of the derived class you may invoke the method of base class with the same name, but with methods defined in constructor, you cannot do this.
Background
I have a prototype object that has dozens of functions that access info from a list like this:
var prototype_object = {
yellow: function(list) { return list[this.type+'_yellow']; },
green: function(list) { return list[this.type+'_green']; },
// ... 50 more functions here
}
The 'this.type' is supposed to come from the object that is assigned the prototype in a function:
function accessor(type) {
var widget = Object.create(prototype_object);
widget.type = type;
return widget;
}
I have a central list of information so now I can call:
var access_foo = accessor('foo'); // Create the accessor
access_foo.green(list); //Find 'foo_green' in the list
Problem
These accessor fxns are passed to different areas of the app and called after being assigned to new objects. Thus the 'this' in the prototype functions is being reassigned (as expected in javascript) and resulting in undefined types.
"SO BIND IT": We can bind to functions to set the 'this' which will create new functions. I can't afford to instantiate 60 new functions for 100s of dozens of object types in dozens of places.
"CALL IT": Call would require that I pass the original accessor as the 'this', but as I said, access_foo.green is passed somewhere else in the app and cannot reference back to access_foo on call.
"CHANGE THE PROTOTYPE_OBJECT PARAMS": Not an option the way the app is written.
In the end I need an object that knows its type and shares access to a large list of functions. Am I right in saying there's no way to create custom accessors that can be called out of context without having them all instantiate/bind to the full set of possible prototype functions?
You seem to have ruled out all the possible solutions. If you want a solution, you will have to adapt to use one of the options. If you're passing around accessor functions lots of places and you want them permanently bound to your object (so you don't have to also pass the object), then you will have to change how you're doing things.
The cleanest way would be to define the methods in the constructor and have the methods use a constructor local variable for the object reference and rely on the constructor closure instead of using this. Then, they would still work even though this was wrong. You will have to redo how you create your object in order to do that.
You could also redefine all your methods to pre-bind themselves. I will show code examples of both options.
Here's the closure method:
function myObj() {
var self = this;
self.prop1 = "foo";
// define all methods in here and use self instead of this
self.method1 = function() {
console.log(self.prop1);
}
}
var x = new myObj();
var m = x.method1;
m();
And, here's the pre-bind method while changing as little as possible of your existing code:
var prototype_object = {
yellow: function(list) { return list[this.type+'_yellow']; },
green: function(list) { return list[this.type+'_green']; },
// ... 50 more functions here
}
function accessor(type) {
var widget = Object.create(prototype_object);
widget.type = type;
// reassign prototype methods to the actual object and make them pre-bound
// to this particular instance
for (var method in prototype_object) {
if (typeof method === "function") {
// assign pre-bound method to the instance
widget[method] = widget[method].bind(widget);
}
}
return widget;
}
This one is a little more optimized version of the previous one that doesn't put the new methods on the prototype at all:
var prototype_object = {
yellow: function(list) { return list[this.type+'_yellow']; },
green: function(list) { return list[this.type+'_green']; },
// ... 50 more functions here
}
function accessor(type) {
var widget = {};
widget.type = type;
// reassign prototype methods to the actual object and make them pre-bound
// to this particular instance
for (var method in prototype_object) {
if (typeof method === "function" && prototype_object.hasOwnProperty(method)) {
// assign pre-bound method to the instance
widget[method] = prototype_object[method].bind(widget);
}
}
return widget;
}
I just read a few threads on the discussion of singleton design in javascript. I'm 100% new to the Design Pattern stuff but as I see since a Singleton by definition won't have the need to be instantiated, conceptually if it's not to be instantiated, in my opinion it doesn't have to be treated like conventional objects which are created from a blueprint(classes). So my wonder is why not just think of a singleton just as something statically available that is wrapped in some sort of scope and that should be all.
From the threads I saw, most of them make a singleton though traditional javascript
new function(){}
followed by making a pseudo constructor.
Well I just think an object literal is enough enough:
var singleton = {
dothis: function(){},
dothat: function(){}
}
right? Or anybody got better insights?
[update] : Again my point is why don't people just use a simpler way to make singletons in javascript as I showed in the second snippet, if there's an absolute reason please tell me. I'm usually afraid of this kind of situation that I simplify things to much :D
I agree with you, the simplest way is to use a object literal, but if you want private members, you could implement taking advantage of closures:
var myInstance = (function() {
var privateVar;
function privateMethod () {
// ...
}
return { // public interface
publicMethod1: function () {
// private members can be accessed here
},
publicMethod2: function () {
// ...
}
};
})();
About the new function(){} construct, it will simply use an anonymous function as a constructor function, the context inside that function will be a new object that will be returned.
Edit: In response to the #J5's comment, that is simple to do, actually I think that this can be a nice example for using a Lazy Function Definition pattern:
function singleton() {
var instance = (function() {
var privateVar;
function privateMethod () {
// ...
}
return { // public interface
publicMethod1: function () {
// private members can be accessed here
},
publicMethod2: function () {
// ...
}
};
})();
singleton = function () { // re-define the function for subsequent calls
return instance;
};
return singleton(); // call the new function
}
When the function is called the first time, I make the object instance, and reassign singleton to a new function which has that object instance in it's closure.
Before the end of the first time call I execute the re-defined singleton function that will return the created instance.
Following calls to the singleton function will simply return the instance that is stored in it's closure, because the new function is the one that will be executed.
You can prove that by comparing the object returned:
singleton() == singleton(); // true
The == operator for objects will return true only if the object reference of both operands is the same, it will return false even if the objects are identical but they are two different instances:
({}) == ({}); // false
new Object() == new Object(); // false
I have used the second version (var singleton = {};) for everything from Firefox extensions to websites, and it works really well. One good idea is to not define things inside the curly brackets, but outside it using the name of the object, like so:
var singleton = {};
singleton.dothis = function(){
};
singleton.someVariable = 5;
The ES5 spec lets us use Object.create():
var SingletonClass = (function() {
var instance;
function SingletonClass() {
if (instance == null) {
instance = Object.create(SingletonClass.prototype);
}
return instance;
}
return {
getInstance: function() {
return new SingletonClass();
}
};
})();
var x = SingletonClass.getInstance();
var y = SingletonClass.getInstance();
var z = new x.constructor();
This is nice, since we don't have to worry about our constructor leaking, we still always end up with the same instance.
This structure also has the advantage that our Singleton doesn't construct itself until it is required. Additionally, using the closure as we do here prevents external code from using our "instance" variable, accidentally or otherwise. We can build more private variables in the same place and we can define anything we care to export publically on our class prototype.
The singleton pattern is implemented by creating a class with a method that creates a new instance of the class if one does not exist. If an instance already exists, it simply returns a reference to that object. 1
(function (global) {
var singleton;
function Singleton () {
// singleton does have a constructor that should only be used once
this.foo = "bar";
delete Singleton; // disappear the constructor if you want
}
global.singleton = function () {
return singleton || (singleton = new Singleton());
};
})(window);
var s = singleton();
console.log(s.foo);
var y = singleton();
y.foo = "foo";
console.log(s.foo);
You don't just declare the singleton as an object because that instantiates it, it doesn't declare it. It also doesn't provide a mechanism for code that doesn't know about a previous reference to the singleton to retrieve it. The singleton is not the object/class that is returned by the singleton, it's a structure. This is similar to how closured variables are not closures, the function scope providing the closure is the closure.
I am just posting this answer for people who are looking for a reliable source.
according to patterns.dev by Lydia Hallie, Addy Osmani
Singletons are actually considered an anti-pattern, and can (or.. should) be avoided in JavaScript.
In many programming languages, such as Java or C++, it's not possible to directly create objects the way we can in JavaScript. In those object-oriented programming languages, we need to create a class, which creates an object. That created object has the value of the instance of the class, just like the value of instance in the JavaScript example.
Since we can directly create objects in JavaScript, we can simply use
a regular object to achieve the exact same result.
I've wondered about this too, but just defining an object with functions in it seems reasonable to me. No sense creating a constructor that nobody's ever supposed to call, to create an object with no prototype, when you can just define the object directly.
On the other hand, if you want your singleton to be an instance of some existing "class" -- that is, you want it to have some other object as its prototype -- then you do need to use a constructor function, so that you can set its prototype property before calling it.
The latter code box shows what I've seen JS devs call their version of OO design in Javascript.
Singetons are meant to be singular objects that can't be constructed (except, I suppose, in the initial definition. You have one, global instance of a singleton.
The point of using the "pseudo constructor" is that it creates a new variable scope. You can declare local variables inside the function that are available inside any nested functions but not from the global scope.
There are actually two ways of doing it. You can call the function with new like in your example, or just call the function directly. There are slight differences in how you would write the code, but they are essentially equivalent.
Your second example could be written like this:
var singleton = new function () {
var privateVariable = 42; // This can be accessed by dothis and dothat
this.dothis = function () {
return privateVariable;
};
this.dothat = function () {};
}; // Parentheses are allowed, but not necessary unless you are passing parameters
or
var singleton = (function () {
var privateVariable = 42; // This can be accessed by dothis and dothat
return {
dothis: function () {
return privateVariable;
},
dothat: function () {}
};
})(); // Parentheses are required here since we are calling the function
You could also pass arguments to either function (you would need to add parentheses to the first example).
Crockford (seems to) agree that the object literal is all you need for a singleton in JavaScript:
http://webcache.googleusercontent.com/search?q=cache:-j5RwC92YU8J:www.crockford.com/codecamp/The%2520Good%2520Parts%2520ppt/5%2520functional.ppt+singleton+site:www.crockford.com&cd=1&hl=en&ct=clnk
How about this:
function Singleton() {
// ---------------
// Singleton part.
// ---------------
var _className = null;
var _globalScope = null;
if ( !(this instanceof arguments.callee) ) {
throw new Error("Constructor called as a function.");
}
if ( !(_className = arguments.callee.name) ) {
throw new Error("Unable to determine class name.")
}
_globalScope = (function(){return this;}).call(null);
if ( !_globalScope.singletons ) {
_globalScope.singletons = [];
}
if ( _globalScope.singletons[_className] ) {
return _globalScope.singletons[_className];
} else {
_globalScope.singletons[_className] = this;
}
// ------------
// Normal part.
// ------------
var _x = null;
this.setx = function(val) {
_x = val;
}; // setx()
this.getx = function() {
return _x;
}; // getx()
function _init() {
_x = 0; // Whatever initialisation here.
} // _init()
_init();
} // Singleton()
var p = new Singleton;
var q = new Singleton;
p.setx(15);
q.getx(); // returns 15
I stole this from CMS / CMS' answer, and changed it so it can be invoked as:
MySingleton.getInstance().publicMethod1();
With the slight alternation:
var MySingleton = { // These two lines
getInstance: function() { // These two lines
var instance = (function() {
var privateVar;
function privateMethod () {
// ...
console.log( "b" );
}
return { // public interface
publicMethod1: function () {
// private members can be accessed here
console.log( "a" );
},
publicMethod2: function () {
// ...
privateMethod();
}
};
})();
singleton = function () { // re-define the function for subsequent calls
return instance;
};
return singleton(); // call the new function
}
}
I'm trying to generate a class from an object in JavaScript. For example:
var Test = {
constructor: function() { document.writeln('test 1'); },
method: function() { document.writeln('test 2'); }
};
var TestImpl = function() { };
TestImpl.prototype.constructor = Test.constructor;
TestImpl.prototype.method = Test.method;
var x = new TestImpl();
x.method();
But this doesn't work: it'll only write 'test 2' (for whatever reason, constructor isn't being defined properly). Why?
I think you're doing it wrong.
Remember, JavaScript doesn't actually have classes at all. It has prototypes instead. So what you're really trying to do is create a prototype object that works like a collection of functions that you've built on another object. I can't imagine any useful purpose for this -- could you elaborate as to what you're trying to do?
Although I think you could make it work by using something like:
var TestImpl = function() {
Test.constructor.apply(this);
};
TestImpl.prototype.method = Test.method;
Your TestImpl function is the constructor. Usually you would do something like this:
var Test1 = function () {
document.writeln('in constructor');
};
Test1.prototype = {
x: 3,
method1: function() { document.writeln('x='+this.x); }
}
var y1 = new Test1();
y1.method1();
y1.x = 37;
y1.method1();
var y2 = new Test1();
y2.method1();
y2.x = 64;
y2.method1();
I think you have things a little backwards. Usually you will assign a prototype to a constructor, rather than assigning a constructor to a prototype.
The reason for assigning a method to the constructor's prototype, rather than to the "this" object inside the constructor, is that the former method creates only 1 shared function, whereas the latter method creates separate instances of a function. This is important (to keep memory allocation to a reasonable amount) if you create lots of objects each with lots of methods.
var Test = function () {
document.writeln('test 1');
this.method = function() { document.writeln('test 2'); }
};
var x = new Test();
x.method();
Javascript doesn't have a "Class" concept, It's all about prototype and the way you use them [ and you can simulate any kind of inheritance with this little neat feature. ]
In javascript "Function" plays the role of [ Class, Method and Constructor ].
so inorder to create "Class" behaviour in Javascript all you need to do is to use the power of "Function".
var A = function(){
alert('A.Constructor');
}
A.prototype = {
method : function(){
alert('A.Method');
}
}
var b = new A(); // alert('A.Constructor');
b.method(); // alert('A.Method');
now the neat thing about JS is that you can easily create "Inheritance" behaviour by using the same method. All you need to do is to connect the second class "Prototype Chain" to the first one, How?
B = function(){
this.prototype = new A(); // Connect "B"'s protoype to A's
}
B.prototype.newMethod = function() { alert('testing'); }
var b = new B();
b.method(); // Doesn't find it in B's prototype,
// goes up the chain to A's prototype
b.newMethod(); // Cool already in B's prototype
// Now when you change A, B's class would automatically change too
A.prototype.method = function(){ alert('bleh'); }
b.method(); // alert('bleh')
If you need any more references I suggest to take a look at Douglas Crockford's Site
Happy JS ing.
Well I tried to figure out is this possible in any way. Here is code:
a=function(text)
{
var b=text;
if (!arguments.callee.prototype.get)
arguments.callee.prototype.get=function()
{
return b;
}
else
alert('already created!');
}
var c=new a("test"); // creates prototype instance of getter
var d=new a("ojoj"); // alerts already created
alert(c.get()) // alerts test
alert(d.get()) // alerts test from context of creating prototype function :(
As you see I tried to create prototype getter. For what? Well if you write something like this:
a=function(text)
{
var b=text;
this.getText=function(){ return b}
}
... everything should be fine.. but in fact every time I create object - i create getText function that uses memory. I would like to have one prototypical function lying in memory that would do the same... Any ideas?
EDIT:
I tried solution given by Christoph, and it seems that its only known solution for now. It need to remember id information to retrieve value from context, but whole idea is nice for me :) Id is only one thing to remember, everything else can be stored once in memory. In fact you could store a lot of private members this way, and use anytime only one id. Actually this is satisfying me :) (unless someone got better idea).
someFunc = function()
{
var store = new Array();
var guid=0;
var someFunc = function(text)
{
this.__guid=guid;
store[guid++]=text;
}
someFunc.prototype.getValue=function()
{
return store[this.__guid];
}
return someFunc;
}()
a=new someFunc("test");
b=new someFunc("test2");
alert(a.getValue());
alert(b.getValue());
JavaScript traditionally did not provide a mechanism for property hiding ('private members').
As JavaScript is lexically scoped, you could always simulate this on a per-object level by using the constructor function as a closure over your 'private members' and defining your methods in the constructor, but this won't work for methods defined in the constructor's prototype property.
Of course, there are ways to work around this, but I wouldn't recommend it:
Foo = (function() {
var store = {}, guid = 0;
function Foo() {
this.__guid = ++guid;
store[guid] = { bar : 'baz' };
}
Foo.prototype.getBar = function() {
var privates = store[this.__guid];
return privates.bar;
};
Foo.prototype.destroy = function() {
delete store[this.__guid];
};
return Foo;
})();
This will store the 'private' properties in another object seperate from your Foo instance. Make sure to call destroy() after you're done wih the object: otherwise, you've just created a memory leak.
edit 2015-12-01: ECMAScript6 makes improved variants that do not require manual object destruction possible, eg by using a WeakMap or preferably a Symbol, avoiding the need for an external store altogether:
var Foo = (function() {
var bar = Symbol('bar');
function Foo() {
this[bar] = 'baz';
}
Foo.prototype.getBar = function() {
return this[bar];
};
return Foo;
})();
With modern browsers adopting some ES6 technologies, you can use WeakMap to get around the GUID problem. This works in IE11 and above:
// Scope private vars inside an IIFE
var Foo = (function() {
// Store all the Foos, and garbage-collect them automatically
var fooMap = new WeakMap();
var Foo = function(txt) {
var privateMethod = function() {
console.log(txt);
};
// Store this Foo in the WeakMap
fooMap.set(this, {privateMethod: privateMethod});
}
Foo.prototype = Object.create(Object.prototype);
Foo.prototype.public = function() {
fooMap.get(this).p();
}
return Foo;
}());
var foo1 = new Foo("This is foo1's private method");
var foo2 = new Foo("This is foo2's private method");
foo1.public(); // "This is foo1's private method"
foo2.public(); // "This is foo2's private method"
WeakMap won't store references to any Foo after it gets deleted or falls out of scope, and since it uses objects as keys, you don't need to attach GUIDs to your object.
Methods on the prototype cannot access "private" members as they exist in javascript; you need some kind of privileged accessor. Since you are declaring get where it can lexically see b, it will always return what b was upon creation.
After being hugely inspired by Christoph's work-around, I came up with a slightly modified concept that provides a few enhancements. Again, this solution is interesting, but not necessarily recommended. These enhancements include:
No longer need to perform any setup in the constructor
Removed the need to store a public GUID on instances
Added some syntactic sugar
Essentially the trick here is to use the instance object itself as the key to accessing the associated private object. Normally this is not possible with plain objects since their keys must be strings. However, I was able to accomplish this using the fact that the expression ({} === {}) returns false. In other words the comparison operator can discern between unique object instances.
Long story short, we can use two arrays to maintain instances and their associated private objects:
Foo = (function() {
var instances = [], privates = [];
// private object accessor function
function _(instance) {
var index = instances.indexOf(instance), privateObj;
if(index == -1) {
// Lazily associate instance with a new private object
instances.push(instance);
privates.push(privateObj = {});
}
else {
// A privateObject has already been created, so grab that
privateObj = privates[index];
}
return privateObj;
}
function Foo() {
_(this).bar = "This is a private bar!";
}
Foo.prototype.getBar = function() {
return _(this).bar;
};
return Foo;
})();
You'll notice the _ function above. This is the accessor function to grab ahold of the private object. It works lazily, so if you call it with a new instance, it will create a new private object on the fly.
If you don't want to duplicate the _ code for every class, you can solve this by wrapping it inside a factory function:
function createPrivateStore() {
var instances = [], privates = [];
return function (instance) {
// Same implementation as example above ...
};
}
Now you can reduce it to just one line for each class:
var _ = createPrivateStore();
Again, you have to be very careful using this solution as it can create memory leaks if you do not implement and call a destroy function when necessary.
Personally, I don't really like the solution with the guid, because it forces the developer to declare it in addition to the store and to increment it in the constructor. In large javascript application developers might forget to do so which is quite error prone.
I like Peter's answer pretty much because of the fact that you can access the private members using the context (this). But one thing that bothers me quite much is the fact that the access to private members is done in a o(n) complexity. Indeed finding the index of an object in array is a linear algorithm. Consider you want to use this pattern for an object that is instanciated 10000 times. Then you might iterate through 10000 instances each time you want to access a private member.
In order to access to private stores in a o(1) complexity, there is no other way than to use guids. But in order not to bother with the guid declaration and incrementation and in order to use the context to access the private store I modified Peters factory pattern as follow:
createPrivateStore = function () {
var privates = {}, guid = 0;
return function (instance) {
if (instance.__ajxguid__ === undefined) {
// Lazily associate instance with a new private object
var private_obj = {};
instance.__ajxguid__ = ++guid;
privates[instance.__ajxguid__] = private_obj;
return private_obj;
}
return privates[instance.__ajxguid__];
}
}
The trick here is to consider that the objects that do not have the ajxguid property are not yet handled. Indeed, one could manually set the property before accessing the store for the first time, but I think there is no magical solution.
I think real privacy is overrated. Virtual privacy is all that is needed. I think the use of _privateIdentifier is a step in the right direction but not far enough because you're still presented with a listing of all the _privateIdentifiers in intellisense popups. A further and better step is to create an object in the prototype and/or constructor function for segregating your virtually private fields and methods out of sight like so:
// Create the object
function MyObject() {}
// Add methods to the prototype
MyObject.prototype = {
// This is our public method
public: function () {
console.log('PUBLIC method has been called');
},
// This is our private method tucked away inside a nested privacy object called x
x: {
private: function () {
console.log('PRIVATE method has been called');
}
},
}
// Create an instance of the object
var mo = new MyObject();
now when the coder types "mo." intellisense will only show the public function and "x". So all the private members are not shown but hidden behind "x" making it more unlikely for a coder to accidentally call a private member because they'll have to go out of their way and type "mo.x." to see private members. This method also avoids the intellisense listing from being cluttered with multiple private member names, hiding them all behind the single item "x".
I know this thread is really really old now, but thought this solution might be of interest to anyone passing by:
const Immutable = function ( val ) {
let _val = val;
this.$ = {
_resolve: function () {
return _val;
}
};
};
Immutable.prototype = {
resolve: function () {
return this.$._resolve();
}
};
Essentially hiding the internal _val from being manipulated and making an instance of this object immutable.
I have created a new library for enabling private methods on the prototype chain.
https://github.com/TremayneChrist/ProtectJS
Example:
var MyObject = (function () {
// Create the object
function MyObject() {}
// Add methods to the prototype
MyObject.prototype = {
// This is our public method
public: function () {
console.log('PUBLIC method has been called');
},
// This is our private method, using (_)
_private: function () {
console.log('PRIVATE method has been called');
}
}
return protect(MyObject);
})();
// Create an instance of the object
var mo = new MyObject();
// Call its methods
mo.public(); // Pass
mo._private(); // Fail