Closure versus regular constructor function for creating private properties? - javascript

I've heard that one of the advantages of closures is the ability to create private properties for objects as follows.
function Func2(){
//A is a closure, kept alive after the Func2 has returned,
//After Func2 returns, A is only accessible by getA and setA (it's "private")
var A = 100;
return {
getA: function(){
return A;
},
setA: function(newA){
A = newA;
}
}
}
You can get and set the private property A of an object created with Func2 using the getter and setter functions...
var obj2 = Func2();
obj2.getA();
obj2.setA(200);
But what's the point of that if I can do the same thing using a regular constructor function?
function Func1(){
var A = 100; //A is a private property of any object created with the Func1 constructor
this.getA = function(){
return A;
};
this.setA = function(newA){
A = newA;
};
}
Accessing the private properties is done the same way...
var obj1 = new Func1()
obj1.getA();
obj1.setA(200);

As others have pointed out in the comments, a closure is created in both cases, and both will work.
I think the reason that the return approach is recommended for the module pattern is that the module pattern does not make use of Javascript's prototype chain, so it's unnecessary to use a regular constructor function that would create a new prototype (which isn't needed and would waste memory). In your example, objects created by Func2 would just have the default prototype of Object.prototype, whereas objects created by Func1 would have a prototype of Func1.prototype which in turn would have the prototype Object.prototype. Also, Func2 has the advantage that it will work with or without the new keyword (although it's best to avoid the new keyword if you're using the module pattern for the reasons I mentioned above). (I have seen some programmers complain about the fact that if a programmer forgets the new keyword in traditional OO Javascript, it can cause hard-to-detect bugs; I personally have never found this to be an issue though).
Another approach to private variables, as you're probably aware, is to simply prefix them with _, e.g.:
function Func1() {
this._A = 100;
}
Func1.prototype = {
constructor: Func1,
getA: function(){
return this._A;
},
setA: function(newA){
this._A = newA;
}
};
Personally I prefer this over the module pattern - the main goal of private variables is communication to other programmers, i.e. "this is an internal property; don't access it directly" - and the underscore prefix is a well-known convention. Private properties have never really been about 100% preventing access to those properties, just discouraging it (consider the fact that most programming languages allow you to access private properties using reflection if you really want to). And also, simply prefixing with an underscore allows you to easily have "protected" properties in addition to private ones (useful for sub-types / sub-classes). Making use of the prototype chain is also more memory-efficient, because you don't have multiple copies of the same functions for each instance.
But I do realize that in spite of the simplicity of the underscore naming convention, some programmers still prefer using the module pattern to really make private properties inaccessible from outside the closure. If you want to do that, then I'd recommend using the traditional module pattern, using the return statement as in your first example.
Another pattern you could consider, if you prefer to stick with the module pattern but still want to declare public properties as you go along (rather than in a return statement at the end), would be to create a new object and use that instead of this, e.g.:
function Func3(){
var obj = {};
var A = 100;
obj.getA = function(){
return A;
};
obj.setA = function(newA){
A = newA;
};
return obj;
}
(By the way, for private methods, as opposed to private data properties, the underscore prefix isn't a necessity even if you're using the prototypal approach. The code sample in this answer is an example of this.)

Related

Constructor vs. closure?

What exactly is different about these 2 objects, a created using a constructor, b using a closure?
Is the property __proto__ useful for anything that cannot be achieved by using a closure? Am I supposed to use these techniques in different situations? Is there a difference in memory usage?
(jsFiddle)
window.MODULE = {};
MODULE.constructor = function(){
this.publicVariable = 10;
};
MODULE.constructor.prototype.publicMethod = function(){
return this.publicVariable;
};
//-------------------------------//
MODULE.closure = (function(){
var publicMethod = function(){
return this.publicVariable;
};
return function(){
var obj = {};
obj.publicVariable = 10;
obj.publicMethod = publicMethod;
return obj;
};
}());
//-------------------------------//
var a = new MODULE.constructor();
console.log("constructor", a.publicMethod(), a)
var b = MODULE.closure();
console.log("closure", b.publicMethod(), b)
Also see a more complicated jsFiddle comparison with some private and static properties - both techniques work the same as far as I can tell...
Roughly, the main advantages of prototypal inheritance (your "constructor" method) are makes it easier to do subclasses and monkeypatching (adding methods to an existing class) while closures are nice if you want private instance variables and methods ("protected methods" are still hard to do with either method) or prefer lexical scoping instead of dynamic scoping with "this" (useful if someone does setTimeout(obj.method, 1000))
As for performance, prototypal inheritance can be a bit more efficient because implementations are tuned to it but it really shouldn't matter unless you instantiate lots of objects from that class.
Private variable example:
var counter = function(){
var count = 0; //private variable
var increment = function(){ // private method
count ++;
};
return { //public interface
next: function(){
increment();
return count;
},
}
}
var c = counter();
console.log(c.next());
console.log(c.next());
If we skip the advantages of OOP approach, difference between a and b is that b has own method publicMethod, when a inherits this method from it's prototype:
a.hasOwnProperty('publicMethod'); // false
b.hasOwnProperty('publicMethod'); // true
Note, that __proto__ property is non-standard and not supported in IE < 11. Alternatively you may use ES5 feature Object.getPrototypeOf(a).
Also note naming conventions it JavaScript1:
UPPER_CASE is used for constants, when globals usually use PascalCase, so your MODULE should be Module;
constructors use PascaleCase too, so your MODULE.constructor should be Module.Constructor.
More on prototype, inheritance, overriding and calling super here: https://stackoverflow.com/a/16063711/1641941
MODULE={};
MODULE.constructor = function(){
this.publicVariable = 10;
};
MODULE.constructor.prototype=(function(){
var privateMethod=function(){
console.log("I'm private");
};
return {
publicMethod : function(){
//going to call "private" method
privateMethod();
return this.publicVariable;
}
};
}());
var c = new MODULE.constructor();
c.publicMethod();
To have instance specific "private" member values you have to give up prototype because you have to define all functions accessing these values in the constructor function body instead of on the prototype. I personally think it's silly to forcefully implement something that is not supported by JavaScript (private instance specific variables) and by doing so giving up something that is supported by JavaScript (prototype).
By supported I mean that JS engines will optimise your code for it.

Using prototype and dealing with execution order

I'm trying to get a really solid grasp of JavaScript and I'm stumbling across a big issue for me. I'm used to working in C languages and one of the barriers I'm finding is dealing with the prototype functionality of JavaScript and when functions are declared, as it is concerned with the order of execution.
For instance, take the following code:
var construct = new Constructor(); //I can do this even if its above the declaration of the object.
construct.MyPrivilagedFunction(); //Can do this here too, even though it's above the function declaration.
construct.MyPublicFunction(); //Can't do this because it is above the function declaration.
function Constructor() {
//Private member
var m_Ding = "Ding!";
//Accessible publicly and has access to private member.
this.MyPrivilagedFunction = function() {
console.log(m_Ding);
}
}
Constuctor.prototype.MyPublicFunction = function() {
//Doesn't have access to private members. This doesn't work.
console.log(m_Ding);
}
I understand that prototyping provides better performance because then a copy of the function is not stored on every instance of your object and instead every instance is referring to the same function (and I guess each new instance could be considered a whole new object type?). However, prototyping does not allow me to use a function before it is defined. Furthermore, a prototyped function doesn't have access to a private member of the object.
This is only really a problem because I am working on a project where two objects will need to use each other's functions. If I place one object earlier in the code, it won't have access to the second object because prototyped functions adhere to the order of execution (top to bottom).
Side Note: I'm also aware that my object should probably be an object literal ( like object={property:value}), but I'm still trying to get a solid grasp on scope and prototyping to attempt to deal with that for now.
if i get you well, the root of your problem is "two objects will need to use
each other's functions."
But in fact Javascript is not a typed language : define TypeA, define TypeB,
after that you can use instances : typeA and typeB objects with no issue.
var Speaker = function(name) {
this.name = name ;
};
Speaker.prototype.sayHi = function(aMate) {
amate.listenTo(this, ' Hi ' + this.mate.name ); // no type checking performed here
// so no issue even if Listener
// is not defined yet
};
var Listener = function(name) {
this.name = name;
this.knownMate = [];
};
Listener.prototype.listenTo = function (mate, words) {
this.knownMate.push(mate);
};
var aSpeaker = new Speaker('Joe');
var aListener = new Listener('Bobby');
aSpeaker.sayHi(aListener);
And by the way, you do not have private members in Javascript, only closures.
So yes, any function defined outside the scope of the 'private' member will
not be able to read/write to it.
Be advised also that, if performance is an issue, closures are slower on the
less performant js engine.
A not-so-bad solution to have 'pseudo-private' members is to define those members
as not enumerable with Object.defineProperty()
(watch here :
https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Object/defineProperty )
The order of execution is the one you write. There are only two exceptions from the rule "everything below is irrelevant": variable and function declarations are hoisted, i.e. you can use (assign to, call) them above. And beware of the difference between function declarations and function expressions.
var construct = new Constructor() //I can do this even if its above the declaration of the object.
Declaration of the constructor function you want to say.
construct.MyPrivilagedFunction(); //Can do this here too, even though it's above the function declaration.
There is no function declaration in here. The privileged method was created (with an assignment of a function expression to a property) during the execution of the constructor function (see above).
construct.MyPublicFunction(); //Can't do this because it is above the function declaration.
Again, it is no function declaration but an assignment of a function expression. And it didn't happen yet, because it is below.
This is only really a problem because I am working on a project where two objects will need to use each other's functions. If I place one object earlier in the code, it won't have access to the second object because prototyped functions adhere to the order of execution (top to bottom).
You usually don't need access to anything before you call anything. "Declare" everything at first (constructor, prototype properties), then instantiate.

When should I use `this.x` vs. `var x`?

While making a JavaScript class function, I’m using this. A lot. But while using that, it’s making me wonder whether it would’ve made a difference to use var instead.
var MyClass = function() {
this.x = 4;
return {
getVal: this.x
};
}
versus the same thing with the use of var:
var MyClass = function() {
var x = 4;
return {
getVal: x
};
}
What’s the difference and when should I use which?
The same question applies to the class syntax:
class MyClass {
constructor(){
const x = 4;
}
}
versus
class MyClass {
constructor(){
this.x = 4;
}
}
Identifiers with this become public properties, whereas those with var become private variables.
Nowadays, const should be used instead of var; if you can’t use const for a specific variable, use let instead.
The access semantics are the same.
When using an identifier with the this keyword, like this.x = 4;, you’re setting a property with the key "x" and the value 4 on the object referenced by this. Since this refers to the instance in the context of a class, such properties become instance members of the class, which means they will be available in each newly created instance of that class. When you use this, it means that your intention is to use it in a class, so you need to instantiate it using the new keyword as shown below.
Example
function Foo() {
// Variables, scoped to the function. Private access.
const bar = 'I am bar';
// Properties, set on the instance. Public access
this.baz = 'I am baz';
this.secretBar = () => `It’s a secret to everybody: ${bar}.`;
}
const f = new Foo();
console.log(f.bar); // undefined
console.log(f.baz); // "I am baz"
console.log("bar" in f); // false; f does not have the property "bar".
console.log(f.secretBar()); // "It’s a secret to everybody: I am baz.";
// `secretBar` is in the scope of `Foo`, so it has access to its variables.
While making a JavaScript class function, I’m using this.
A lot.
But while using that, it’s making me wonder whether it would’ve made a difference to use var instead.
There is a significant difference. You should not create variables with the this keyword that you don’t want to appear in instances of your class, unless otherwise needed.
You can access this.x with myClass.x, but you can't do that for var x case. This is all about encapsulation.
If you are not going to need to do inheritance, closures (the var case) and objects (the this case) basically do the same thing and are roughly interchangeable.
Differences to keep in mind:
When you use "this" the constructor needs to be called with "new" and methods need to be called with .call if you store them on a variable or pass them as a callback.
There might be performance differences if you instantiate lots of objects (current engines may with objects better - but only if you put the methods in the prototype instead of setting them in the constructor)
Variables declared with "var" are private and cannot be accessed outside the function. Sometimes this is OK but this can stop you from doing inheritance (there is no notion of "protected in Javascript")
Expressions like this.x refer to properties; they are like instance variables. These variables have public scope. They work as class variables in object oriented programming.
On the other hand, var x; has limited scope. These are variables that behave like private instance variables and are accessible within the local scope.

is there a way to inject privileged methods after an object is constructed?

I'm trying to write fully automated unit tests in JavaScript and I'm looking for a way to read some private variables in various JS functions. I thought I recalled a way to inject privileged members into a function/object (and found an overwhelming occurrence of "no such thing as private in JS") and yet I can't find any resources indicating how.
I'm trying to read through the properties of .prototype but if there's a way, someone out here would know where to direct me faster than I'd find on my own.
Thanks
Update
Privileged means a function that is usable from outside an object and has access to read "private" variables (variables otherwise unable to read from outside). See http://javascript.crockford.com/private.html for Crockford's explanations.
A sample of the function I'm trying to inject to is o2, where I need to validate the value of x (this is a simplified example, the actual code does some transformations and sends them off to other functions which I plan on testing separately).
var o2 = function() {
var x = 'me';
};
Update 2:
Thanks to everyone who's taken the time to respond. I'm seeing that the overwhelming response here is, "private is private" despite the commentary I see in other SA questions where people say "nothing in JS is private". I guess that is more like rhetorical commentary rather than what I was hoping was some kind of insight into a potential loophole I didn't yet know about.
Correct answer to your question
Even if we try to help you as much as we can, the correct answer to your question is simple:
...you can't
What good would closure variables be if we could access them directly from outside of closure?
if you had an object with private variables, they wouldn't be accessible outside function closure, which is the constructor function.
var c = function() {
var priv = "private";
this.get = function() {
return priv;
};
}
var o = new c();
o.injected = function() {
return priv; // ERROR!!!!!! priv doesn't exist in function scope
};
It is of course different matter if you enclose the whole thing inside a function closure but then you wouldn't have object privates, but rather function closure internals that would be shared among all prototypes within this closure.
(function(){
var intrn = "internal";
// omit "var" to make it global
c = function() {
this.get = function() {
return intrn;
};
};
// omit "var" to make it global
o = new c();
o.injected = function() {
return intrn; // WORKS
};
})();
o.injected();
but this is different than object privates...
Know that I am quite late to the party, but yes it is possible. Although AFAIK it requires use of eval() and a helper method:
function foo(){
var a = 'a';
this.addMethod = function(prop, val){
this[prop] = eval('(' + val.toString() + ')');
}
}
var bar = new foo();
bar.b = 'b';
var Fn = function(){return a + this.b}
bar.addMethod('getValue', Fn);
bar.getValue(); //yields 'ab'
You can use eval() in this case to redefine the function within the context of the closure. However, using eval() is dangerous, ESPECIALLY don't eval() any user input, EVER. However, for use in a testing suite/script it should be fine.
I'd suggest you read Crockford's treatise on how to achieve privileged and private in javascript objects.
If by privileged, you mean methods that are not accessible outside the object, but are callable by other methods and are actually methods on the object, then there really isn't any way to do that because one you put a method on the object, javascript let's anyone call it.
If you just wanted to add a function that was only callable by methods, you could do that by having a private member variable (see how Crockford implements that) that was an object and you could put the methods on that object. Then all existing methods (implemented the way Crockford suggests in the constructor to have access to the private member data) could call those methods. They would technically be members of a different object, but could be given private access to your object's instance data if needed.
It's all pretty convoluted so you'd probably get a better answer if you described the problem you're really trying to solve.
I don't think you can do that. Consider the following code:
function foo() {
var privateVar = 10;
this.privilegedMethod = function() {
return privateVar;
}
}
var obj = new foo();
Here, privilegedMethod has access to privateVar, since it's part of the closure created when the method was defined. Of course, you can always attach a new method to the object after instantiation:
obj.newMethod = function() { return "hello" };
alert(obj.newMethod()); // alerts "hello"
But this new method won't have access to privateVar.

Javascript object definition techniques, pros and cons

What are the basic ways of defining reusable objects in Javascript? I say reusable to exclude singleton techniques, such as declaring a variable with object literal notation directly. I saw somewhere that Crockford defines four such ways in his book(s) but I would rather not have to buy a book for this short bit of information.
Here are the ways I'm familiar with:
Using this, and constructing with new (I think this is called classical?)
function Foo() {
var private = 3;
this.add = function(bar) { return private + bar; }
}
var myFoo = new Foo();
Using prototypes, which is similar
function Foo() {
var private = 3;
}
Foo.prototype.add = function(bar) { /* can't access private, correct? */ }
Returning a literal, not using this or new
function Foo() {
var private = 3;
var add = function(bar) { return private + bar; }
return {
add: add
};
}
var myFoo = Foo();
I can think of relatively minor variations on these that probably don't matter in any significant way. What styles am I missing? More importantly, what are the pros and cons of each? Is there a recommended one to stick to, or is it a matter of preference and a holy war?
Use the prototype. Returning specific objects from constructors makes them non-constructors, and assigning methods to this makes inheritance less convenient.
Returning an object literal
Pros:
If a person forgets new, they still get the object.
You can create truly private variables, since all methods of the object defined inside the constructor share its scope.
Cons:
It’s not a real constructor. Adding something to its prototype won’t change the returned objects, new or no new. new Foo() instanceof Foo would also result in false.
Using prototype
Pros:
You leave the constructor uncluttered.
This is the standard way of doing things in JavaScript, and all built-in constructors put their methods on their prototypes.
Inheritance becomes easier and more correct; you can (and should) use Object.create(ParentConstructor.prototype) instead of new ParentConstructor(), then call ParentConstructor from within Constructor. If you want to override a method, you’re able to do it on the prototype.
You can “modify” objects after they’ve already been created.
You can extend the prototypes of constructors you don’t have access to.
Cons:
It can get to be a bit too verbose, and if you want to change the function’s name, you have to change all of the functions added to the prototype, too. (Either that or define the prototype as one big object literal with a compatible property descriptor for constructor.)
They don’t share an instance-specific scope, so you can’t really have private variables.
Assigning to this.* in the constructor
Pros:
You can use closures and therefore private member variables.
Cons:
No duck typing; you can’t call a method right off of the prototype with any old object. For example, Array.prototype.slice.call(collectionLikeObject).
It's mostly a matter of preference. There's no one way to make Chicken Noodle soup, and uniform objects are the same way.
I don't use any of those 3, although they all work for their own purposes. I use a custom function called Object:deploy, and use it like this..
var a = { hey: 'hello' },
b = {}.deploy(a);
console.log(b.hey); // 'hello'
Using prototype is the best for most people because of automatic trickling.
function A() {};
A.prototype.hello = "Hey";
var a = new A();
console.log(a.hello); // 'Hey'
A.prototype.hello = "Hello";
console.log(a.hello); // 'Hello'
And contrary to popular belief, you can use private variables in prototype.
function Hello() {};
(function () {
var greeting = "Hello";
Hello.prototype.greet = function () { return greeting };
}).apply(this);
But even though that's possible, it's usually better to do..
function Hello() {};
Hello.prototype.greeting = "Hello";
Hello.prototype.greet = function () { return this.greeting };
Well the second approach (prototype) is more similar to standard classes in other languages like Python, in that you have a common "prototype" object which all instances are sharing. To compare the first and second approaches:
In approach 1, every time you call "new Foo()", you are creating a brand new object and inserting all the methods. This isn't very time or space efficient, since each Foo instance will have its own table of all the methods. You can test this by creating two Foo objects, and asking foo1.add == foo2.add (false). Approach 3 is very similar to this; I'm not sure what the semantic difference (if any) there is between approaches 1 and 3.
In approach 2, you have set up a shared prototype object containing all the methods. If you ask foo1.add == foo2.add, you get true. This is more space- and time-efficient. It also lets you add more methods to the prototype after creating instances, and they will see the new methods.
The problem with approach 2, as you say, is that you can't access the private members. But you can still add non-private members to the object itself, and access those using the prototype methods:
function Foo() {
this.private = 3;
}
Foo.prototype.add = function(bar) { return this.private + bar }
A caveat is that foo.private is visible externally.
The prototype one doesn't have a per object instance overhead only a per class overhead for the add function. This alone is the reason why I don't like the other two approaches.
Do not forget about inheritance. Some day you'll need. And for organizing inheritance the best approach is combined technic:
function Foo() {
this.array = [1, 2, 3];
this.add = function(bar) { return private + bar; }
}
Foo.prototype.add = function(bar) { }
var myFoo = new Foo();
Setting fields in constructor is useful to avoid modifying them by children objects.
Setting methods to prototype is faster then doing this every time in constructor.

Categories