How does closure reify the data encapsulation? - javascript

In traditional OOP language, we usually use private/public to implement data encapsulation.
In Javascript, there is no private or public anymore; someone told me; by using closure, the data encapsulation can be implemented. I am wondering how and what's the behind logic?

You can encapsulate data in a 'Class' (no real class before JavaScript 6) this way
var yourClass = function() {
var privateProp = 'sometext'; //private prop
this.prop = 1; //public
this.getPrivateProp = function() {
return privateProp; //access to your private prop with a closure
}
}
var test = new yourClass();
//when you use 'new', everything in 'this' is returned in your object.
//'privateProp' is not in 'this' but 'getPrivateProp' is.
//You got your private data not directly accessible from outside.
test.prop; // 1
test.privateProp;//undefined
test.getPrivateProp();// 'sometext'

Actually isn't creating actual private members.
Check the following code:
function A() {
var doStuff1 = function() { };
this.doStuff2 = function() {
doStuff1();
};
};
var instance = new A();
instance.doStuff2();
Since doStuff2 is declared and added to this, it's part of A instance while doStuff1 is declared as a local variable within the constructor function, and thus, it's only accessible using closures within the same constructor.
BTW I don't like this pattern since it works great when you don't use prototypal inheritance.
Let's say I want to use prototypes:
function A() {
var doStuff1 = function() {}; // ??????
};
A.prototype = {
doStuff2: function() {
// How do I access a local variable defined
// in the constructor function local scope?
}
};
So, the whole pattern works in simple scenarios where you don't want to use prototypal inheritance.
Also, this pattern won't work in scenarios where you want to use Object.create(...), since there's no constructor function at all...
// Constructor isn't ever called...
var instance = Object.create(A.prototype);
So, how you would implement this kind of encapsulation in JavaScript? For now isn't possible, but many libraries and frameworks have opted-in to use naming conventions to let developers know what's consumed by the library/framework code and what's intended for use in actual third-party developments.
For example:
function A() {
};
A.prototype = {
___doStuff1___: function() {},
doStuff2: function() {
this.___doStuff1___();
}
};
After all, this is a naming convention, where members which are sorrounded by ___ are considered private or not intended for third-party developers.
Other libraries/framework use $$ (f.e. Angular, $$privateMember).

Related

Using constructor.prototype method for creating a JavaScript library

I am looking into systems for making JavaScript libraries. I have seen most of the libraries using methods such as "Immediately Invoked Function Expression". This method to me makes the code quite unreadable.
I want to know what are the advantages of using this method?
And what are limitations of using the basic .prototype system for creating a library?
For instance, what is wrong with using this pattern to create a library?:
function Library(){
this.property = 'val';
}
Library.prototype.method = function(){
// a method
}
//and to use the library
var lib = new Library();
Immediately-executed functions are essentially just a means of avoiding polluting the global scope with variables that should be private.
Your approach is fine, but what if you want your library to internally reference private data that should not be part of your public API? Example:
var Some_class = (function() {
var foobar = 'foo'; //private; library can read it but public API can't
var api = function() { /* constructor */ };
api.prototype.method = function() { return foobar == 'foo' ? 1 : 0; }
return api;
})();
var instance = new Some_class();
instance.method();
foobar is a private (i.e. internal) variable for use BY your library, but not publicly accessible via its API.

JavaScript design pattern

can someone please explain to me the following JavaScript design pattern example and what it's trying to accomplish?
var Knockback = { };
Knockback.Observables = (function () {
function Observables(model, mappings_info, view_model) {
this.model = model;
this.mappings_info = mappings_info;
this.view_model = view_model;
//logic in here
}
Observables.prototype.destroy = function () {
//logic in here
this.view_model = null;
this.mappings_info = null;
return this.model = null;
};
return Observables;
})();
Knockback.observables = function(model, mappings_info, view_model, options) {
return new Knockback.Observables(model, mappings_info, view_model, options);
};
Knockback is a namespace. Values are stored inside Knockback so they do not clash with any global variables.
Observables is a constructor sitting inside Knockback. All of the logic is inside a closure ((function () {})()) for modularity
observales is used as a method of returning an instance of Observables, This is a way that people can use whats known as "scope safe constructors". In javascript if you call a constructor without new, then the this object defaults to the window, polluting your global namespace again.
I'm not sure how much you know about javascript, but I hope this helps.
-------------------------------- updated --------------
1) The closure functions the same as without a closure, that is correct (At the time of my answer i didnt know that there were no "private" variables). But this pattern also allows you to place this constructor wherever you please. Imagine if the namespace (Knockback) name changed to KB. You could place the constructor there without even needed to change a line of code inside the closure.
2) The Knockback.observer function may be a bloat (which i personally dont think it is) but the "scope safe" factor is considered a best practise. consider:
var standardCorrectInvokation = new Knockback.Observer('model', 'mappings_info', 'view_model');
var aboutToLooseMyJobInvokation = Knockback.Observer('this', 'is', 'un-intuative');
//goodbye global namespace
alert(window.model); // this
alert(window.mappings_info); // is
alert(window.view_model); // un-intuative
//goodbye job at reputable web firm
Id like to point out that the boys as ES5 camp fixed this problem, but strict mode is not implemented in all browsers yet (IE.. ahem ahem)

Is this a good structure for my jQuery scripts?

I want to keep my scripts organized in one .js file for all my site (I have a mess right now), something like namespaces and classes in C#...
(function ($) {
//private variables
$.divref = $("#divReference");
//Namespaces
window.MySite = {};
window.MySite.Home = {};
window.MySite.Contact = {};
//Public function / method
window.MySite.Home.Init = function(params){
alert("Init");
MySite.Home.PrivateFunction();
$.divref.click(function(){
alert("click");
});
};
//private function / method
MySite.Home.PrivateFunction = function(){
alert("Private");
};
})(jQuery);
Is this an idiomatic layout in jQuery and JScript?
I'll go ahead and post my comment as an answer, though I'm not 100% it addresses your questions about c# namespaces and their parallels in JavaScript (I'm no c# programmer). You're not actually creating private variables because you're attaching them to the $ Object that will exist after this function finishes. If you want private variables you need to use a closure. Those look something like this:
var myObject = function () {
var innerVariable = 'some private value';
return {
getter: function () {
return innerVariable;
}
}
}()
If you attempt to access myObject.innerVariable it will return undefined but if you call myObject.getter() it will return the value correctly. This concept is one you will want to read up on in JavaScript, and for programming in general. Hope that helps.
This is more how I would implement the pattern you are trying to do:
// MySite.Home Extension
window.MySite =
(function ($, root) {
//private variables
var $divref = $("#divReference");
//private function / method
var privateFunction = function(){
alert("Private");
};
root.Home = {};
// Public variable
root.Home.prop = "Click"
//Public function / method
root.Home.Init = function(params){
alert("Init");
private();
$divref.click(function(){
alert(root.Home.prop);
});
};
return root;
})(jQuery, window.MySite || {} );
// MySite.Contact Extension
window.MySite =
(function ($, root) {
root.Contact = {};
// More stuff for contact
return root;
})(jQuery, window.MySite || {} );
The first change is splitting each "namespace" into its own Module pattern, so private variables wont bleed from namespace to namespace (if you do intend them to be private to the namespace, which would be more C# esque). Second is rather than accessing window.MySite, pass in the object that you want to extend (in this case I'm calling it root). This will give you some flexibility.
Your private methods weren't really private. To make a private method, you just want to make a function var that it bound in the closure, but not assigned to a property on the externally visible object. Lastly, you probably don't want to use $.somegarbage. Like mentioned in a comment, you are adding a property to the $ object, which will still be there when the closure is done. If you wanted something close, I would just use $somegarbage which some people seem to like to do, but any variable name will work for private variables, just as long as the variable is bound in the closures scope (not somewhere else)
You are on the right track...
you might want to read up on the Module pattern (more) and closures in javascript to prevent polluting the global namespace.

Properties attaching to wrong object

I've adapted the Crockford object() function so that I can pass in some parameters and autorun an init function in the new object:
function object(o) {
function F() {}
F.prototype = o;
var params = Array.prototype.slice.call(arguments,1);
var obj = new F();
if(params.length) {
obj.init.apply(obj,params);
}
return obj;
}
This works fine most of the time, but within one object I have functions defined as follows:
MY.Object = function() {
function init(element, generator) {
build(element);
// more code after
}
function build(element) {
this._property = "example";
}
return {
init: init;
}
}();
If I then run
My.Object2 = object(MY.Object, "test param");
For some reason _property gets added to the Windows object. This stops if I make build a public method and call it using this.build().
Can anyone explain why this happens?
build, although you've defined it within your class, has no context when you're calling it. So, no context means that this references your window object (within a browser, at least). But, even though you don't have the proper this context, you can still access your variables you've declared within the "private" scope of your class.
Try using build.call(this, element) (function.call is similar to function.apply).
Just know that JavaScript doesn't quite behave the same way as other OO languages you may have used, and that classes, and the notion of private and public (among other language features) are a bit of a hack.

Javascript: Access the right scope "under" apply(...)

This is a very old problem, but I cannot seem to get my head around the other solutions presented here.
I have an object
function ObjA() {
var a = 1;
this.methodA = function() {
alert(a);
}
}
which is instantiated like
var myObjA = new ObjA();
Later on, I assign my methodA as a handler function in an external Javascript Framework, which invokes it using the apply(...) method.
When the external framework executes my methodA, this belongs to the framework function invoking my method.
Since I cannot change how my method is called, how do I regain access to the private variable a?
My research tells me, that closures might be what I'm looking for.
You already have a closure. When methodA is called the access to a will work fine.
Object properties are a different thing to scopes. You're using scopes to implement something that behaves a bit like ‘private members’ in other languages, but a is a local variable in the parent scope, and not a member of myObjA (private or otherwise). Having a function like methodA retain access to the variables in its parent scope is what a ‘closure’ means.
Which scopes you can access is fixed: you can always access variables in your parent scopes however you're called back, and you can't call a function with different scopes to those it had when it was defined.
Since a is not a property of this, it doesn't matter that this is not preserved when calling you back. If you do need to get the correct this then yes, you will need some more work, either using another closure over myObjA itself:
onclick= function() { myObjA.methodA(); };
or using Function#bind:
onclick= myObjA.methodA.bind(myObjA);
yes, you're right. Instead of a method reference
var myObjA = new ObjA();
libraryCallback = myObjA.methodA
pass a closure
libraryCallback = function() { myObjA.methodA() }
If you are using jQuery javascript framework, easiest way is to use proxy:
$('a').click($.proxy(myObjA, 'methodA'));
I'd do this:
function ObjA() {
this.a = 1;
this.methodA = function() {
alert(this.a);
}
}
function bindMethod(f, o) {
return function(){
return f.apply(o, arguments);
}
}
var myObjA = new ObjA();
myObjA.methodA = bindMethod(myObjA.methodA, myObjA);
...
Where bindMethod binds the methodA method to always be a method of myObjA while still passing on any arguments which function() {myObjA.methodA()} doesn't do.

Categories