Closures are the most important and least understood. A closure is a way to Remember (keeps things alive!).
So this example only has one closure called increase, and it returns just the one closure.
Block Scoping
Block scoping is not possible with javascript and we have to fake it. For example
// i pollutes it's enclosing scope as i is not within {}, in PHP i would only be scoped to inside the for-loop for(var i = 0, i < 10; i++) { }
Explicit Block Scoping
However, let (and const and class and — in strict mode — function() declarations) have block scope as of ES2015. Which is cool.
https://stackoverflow.com/questions/43016324/javascript-explicit-blocks
var foo = true; if(foo) { { <-- explicit block let bar = foo * 2; bar = something( bar ); console.log( bar ); } }
You can use a standalone block {} for private information and just generally for more finely-controlling the scope of variables, where in the past we used to use IIFEs.
var foo = true; if(foo) { // Private stuff (function() { var x = 1; })(); // `x` doesn't exist here // Private stuff function foo() { var x = 1; } // `x` doesn't exist here // Now, with ES2015, we can do the same thing without creating and calling a function: { let x = 1; } // `x` doesn't exist here }
Function Factory Example
function salary(x) { function increase(y) { // Module Management : Never place private functions outside of the scope in the global space, it's job is related to Salary(). Think of Salary like a controller/class. return x + y; } return increase; } var increaseSalary = salary(1000); // increaseSalary now becomes increase(); as the closure was returned increaseSalary(5); // 1005
Namespace Example (Module Pattern)
Namespace. In JavaScript, it is nothing but a single global object which will contain all our functions, methods, variables and all that.
Namespace we must have known from any language or the other. What it does is, it doesn’t allow us to pollute our code base and makes it cleaner by grouping our code logically and avoiding unexpected and expected collision.
To achieve this, what we need to do is to create a namespace in application and use it.
In any modern day application, Namespace is a must to have because at the end, we need third party libraries and components.
var customerBalance = function balance() { // NOTE: CustomerBalance is a Single Variable Declaration known as a Namespace. Important for collision avoidance to scope the app out of the global space (a wrapper). var balance = 0; // Private function that cannot be accessed outside the scope, no return function changeBy(amount) { balance += amount; } // Only expose these functions return { raise: function(x) { changeBy(x); }, lower: function(x) { changeBy(-x); }, balance: function() { return balance; } }; }; var johnsBalance = customerBalance(); // create a new instance with balance set to zero johnsBalance.raise(500); console.log( johnsBalance.balance() ); johnsBalance.lower(20); console.log( johnsBalance.balance() );
Object Namespace example
var foo = { //name: 'John', setAccount: function(name) { this.name = name; }, balance: function() { this.balance = 0; }, model : { updateBalance() { this.balance = 100; } }, publicApi { getBalance: function() { return this.balance; } } } var user = foo('john'); console.log('Hello my name is ' + user.name + ', my balance is ' + this.balance);
Object Function Example (not a constructor ie. not using New) . It's just a function. Used only once.
function celebrityID () { var celebrityID = 999; // We are returning an object with some inner functions // All the inner functions have access to the outer function's variables return { getID: function () { // This inner function will return the UPDATED celebrityID variable // It will return the current value of celebrityID, even after the changeTheID function changes it return celebrityID; }, setID: function (theNewID) { // This inner function will change the outer function's variable anytime celebrityID = theNewID; } } } var mjID = celebrityID (); // At this juncture, the celebrityID outer function has returned. mjID.getID(); // 999 mjID.setID(567); // Changes the outer function's variable mjID.getID(); // 567: It returns the updated celebrityId variable
Object Function Example as IIFE
var = mjID = (function celebrityID () { var celebrityID = 999; // We are returning an object with some inner functions // All the inner functions have access to the outer function's variables return { getID: function () { // This inner function will return the UPDATED celebrityID variable // It will return the current value of celebrityID, even after the changeTheID function changes it return celebrityID; }, setID: function (theNewID) { // This inner function will change the outer function's variable anytime celebrityID = theNewID; } } })(); mjID.getID(); // 999 mjID.setID(567); // Changes the outer function's variable mjID.getID(); // 567: It returns the updated celebrityId variable
function User() { var username, password; function doLogin() { username = user; password = password; // do rest of login work } var publicAPI = { login: doLogin } return publicAPI } // Create a new user var john = User(); john.login("john","password1"); // Note: the "new" instance isn't used here, it's just a function, not a class, adding new would waste resources.
Closure Example
What is a closure?
A closure is an inner function that has access to the outer (enclosing) function's variables in the lexical scope. You use them all the time.
var Account = function() { var balance = 100; // Closure function balance() { return balance; } return balance; } var balance = Account(); console.log(balance); // 100
Object Literal Closure
Unlike most object-oriented programming languages, JavaScript does not support access modifiers such as, private, protected, and public to specify the accessibility of properties and methods in objects. In JavaScript, all object members are public. In the following example, both the active property and the updateBalance() method are public and therefore can be accessed from anywhere in the program.
Note: Object literals are basically singletons with variables/methods that are ALL PUBLIC. Use this method if there is only ONE instance
var Account = { active: false, // public new: function(name) { this.name = name; this.balance = 0; }, updateBalance: function(amount) { // public this.balance = amount; }, getBalance: function() { // public return this.balance; }, getName: function() { // public return this.name; } } var User = Account; console.log(User.active); // (public property) User.new('John'); // (public method) console.log('Hello my name is ' + User.getName() + ', my balance is ' + User.getBalance()); User.updateBalance(500); // (public method) console.log('Hello my name is ' + User.getName() + ', my balance is ' + User.getBalance());
Function Closure
With object members being so exposed, is there perhaps a way to protect these in JavaScript? The answer is yes, by using function closures.
The objective is to keep some data private without exposing it to the outside world.
http://www.dofactory.com/tutorial/javascript-advanced-objects
**Use the following method if you intend to create more than once instance on the object using the New keyword. All private variables are Var/Const, all public variables will use //this. **
Great explanation.
https://stackoverflow.com/a/12681213
var Account = function(firstname,lastname) { // private properties var tax = 20; // private // public properties this.firstname = firstname; // public this.lastname = lastname; // public this.balanceIncTax = 0; this.balance = 0; // private method function calcTax(amount) { // private method return (amount\100 * tax + amount); }; // privilaged method /* privileged method is a method having access to private properties, but at the same time publicly exposing itself */ this.tax = function tax() { return tax; // known as a lookup } // public method without prototype /* The recommended way for public methods is using the prototype approach */ this.updateBalance = function updateBalance(amount) { this.balance = amount; this.balanceIncTax = calcTax(amount); } } Account.prototype.fullname = function () { return this.firstname + ' ' + this.lastname; }; var User = new Account('John','Carroll'); User.job = 'IT Specialist'; // adding a satic property console.log(User); console.log('Hello my name is ' + User.fullname() + ', my balance is ' + User.balance + ', with tax: '+ User.balanceIncTax ); User.updateBalance(500); // (public method) console.log('Hello my name is ' + User.fullname() + ', my balance is ' + User.balance + ', with tax: '+ User.balanceIncTax );
Difference between Object Literal (singleton) and Constructor Object (new keyword)
// Object Literal - All public (private not allowed) var objLiteral = { x: 0, y: 0, z: 0, add: function () { return this.x + this.y + this.z; } }; // Constructor - Public allowed and we can also created instances of it var ObjConstructor = function(_x, _y, _z) { var x = _x; // private var y = _y; // private this.z = _z; // public this.add = function () { return x + y + this.z; // note x, y doesn't need this. }; }; // Object literal output objLit.x = 3; objLit.y = 2; objLit.z = 1; console.log(objLiteral.add()); // Constructor output var objConstructorInstance = new ObjConstructor(5,4,3); // instantiate an ObjConstructor console.log(objConstructorInstance.add()); console.log((new ObjConstructor(7,8,9)).add()); // another instance of objCon console.log(objConIntance.add()); // same result, not affected by previous line
Instance example (more than once)
var LoginModel = (function(model, window, undefined){ function setName(name){ // constructor this.name = name; // something instance specific } loginModel.prototype.getName = function(){ return this.name; }; return setName; })(MyModel, window); var lm1 = new LoginModel('foo'); var lm2 = new LoginModel('bar'); console.log(lm1.getName(), lm2.getName()); // 'foo', 'bar'
Collision Avoidance
// Avoid this!
function foo() { function bar(i) { i = 1; // use var i = instead } for(var i = 0, i < 10, i++) { bar(i); // i get's reset by bar, NOT GOOD, make sure you user var = in the bar() method } }