When are closures the best way to go in JavaScript?
-
I am looking for examples where closures are the best solution in JavaScript. It will be great if you provide a code snippet of a closure and the non-closure solution and explain why closure is better(for any reason)
-
Answer:
Closures are great. Closures are one of the greatest features of JavaScript. The most basic thing to understand about a closure is that a closure is a function defined in an another scope that has all the access to all the variables within that scope. That says it all one needs to understand about closures. Some of the cases where I prefer to use Closures are: 1. Events and Callbacks Closures help to write non-blocking event driven code. At the beginner level, we go about writing a simple event-driven callback using setTimeout() function call like this: function handleEvent(){ alert(id); } function someEvent(id, timeOut){ setTimeout(handleEvent, timeOut); } someEvent(1,1000); We expect the code to work but it doesn't work because the handleEvent() function doesn't know about the existence of the 'id' variable. So, we get over this using closures like this: function someEvent(id, timeOut) { function handleEvent(){ alert(id); } setTimeout(handleEvent, timeOut); } Another beautiful application of closures is when assigning events. Non-closure way: function assignEvents(arrayofObjects){ for(var i=0;i<arrayofObjects.length;++i){ arrayofObjects[i].onclick = function(i){ alert("You clicked on the object number "+i); } } } In the above implementation, the last value of i is exposed to all the event handler functions, so the code doesn't work the way we expected it to work. So, we solve this problem using closures: function assignEvents( arrayofObjects){ function assignEventHandler(index){ return function(){ alert("You clicked on the object number "+index); } } for(var i=0;i<arrayofObjects.length;++i){ arrayofObjects[i].onclick = assignEventHandler(i); } } In the above code, we used assignEventHandler() function as the outer scope of the closure function() which assigns the event handler to the object. 2. Assigning unique ids to elements Sometimes I often land into situations where I have to assign ids to elements, so to be able to uniquely identify elements, I need to be able to assign them unique ids. I usually solve this problem by using closure to write a helper function to generate ids for elements: var uniqueID = function(){ var id = 0; return function(element){ if(!element.id){ element.id = 'unique-id-' + id; id++; } } } 3. Object reuse This is a clever use of closures to help save run time and memory while cloning objects, i.e. creating objects inheriting from another object. The simplest object cloning code without use of closures: function clone(parent){ function F(){ F.prototype = parent; return new F; } } The above code is slow and consumes too much memory. The function 'F()' is called every time the clone() function is invoked. We don't have to call the function everytime we need to clone the parent, rather we can do it once and reuse it using closure: function clone(parent){ function F(){ return function(parent){ F.prototype = parent; return new F; } } } Instead of the new F object, we are returning the anonymous function inside F() which is reused and no new F is calculated everytime, it is done only once and reused for every other call to clone(). 4. Hiding state and methods in objects This is the most basic use of closures. Read about this http://howtonode.org/why-use-closure One of the best read on closures is http://msdn.microsoft.com/en-us/magazine/ff696765.aspx
Ashish Mehta at Quora Visit the source
Other answers
While the previous answer is certainly thorough, I'd like to offer a real world case example that illustrates the use of a closure that binds a private reference to a WeakMap for storing sensitive information. /** * This is a very simple closure example that uses * an immediately invoked function expression to * as a "reference environment". * */ (function( root ) { /** * Initialize and assign "upvars" that will be bound to * the "close over" function below */ var ref = new WeakMap(); function Ledger( opts ) { var entries; entries = opts.entries ? opts.entries : []; entries.push( opts.balance || 0.00 ); opts.entries = entries; // "ref" is bound to this constructor, // aka. "closed over" ref.set( this, opts ); } Ledger.prototype.balance = function() { // "ref" is bound to this method return (ref.get( this ).entries.reduce(function( prev, curr ) { return prev + curr; }, 0)).toFixed(2) * 1; }; Ledger.prototype.transaction = function( creditOrDebit ) { // "ref" is bound to this method var data = ref.get( this ); // Push the new transaction into the entries array data.entries.push( creditOrDebit ); // Update the private entries array // by setting the data to the bound "ref" key ref.set( this, data ); return this; }; // expose Ledger root.Ledger = Ledger; })( global ); var ledgers; ledgers = { mine: new Ledger({ account: "rjw-10101010101", balance: 100000.00 }), yours: new Ledger({ account: "you-123456789", balance: 0.00 }) }; // the `ledgers` instances do not carry any private data // Make transactions ledgers.mine.transaction(-1234.99); ledgers.mine.transaction(200.50); console.log( ledgers.mine.balance() ); // Make transactions ledgers.yours.transaction(10.00); ledgers.yours.transaction(-9.99); console.log( ledgers.yours.balance() ); // Output: 98965.51 0.01
Rick Waldron
's excellent module pattern is a great example of closures in action. var myModule = ( function(){ var fname = "Phil"; var lname = "Dunphy"; var hobby = "Cracking Jokes and writing Phils-osophy"; var work = function() { console.log( fname + " " + lname + "is a Realtor and his hobby is " + hobby); } return { "hobby" : hobby, "work" : work } })(); myModule.fname; // undefined myModule.lname; // undefined myModule.hobby; // Cracking Jokes and writing Phils-osophy myModule.work(); // Phil Dunphy is a Realtor and his hobby is Cracking Having the closure inside of the module here allows for the programmer to keep certain variables private, and allows for him to generate new public functions, all within the same module! You can read more about what a closure is exactly here:http://www.masterjavascript.io/blog/2016/04/24/understanding-closures/Hope this helps,Erik
Erik Grueter
Related Q & A:
- Is there a way to go from England to Amsterdam by train?Best solution by Yahoo! Answers
- What is the best way to go to the TX Motor Speedway?Best solution by Yahoo! Answers
- When is the best day to go to six flags magic mountain?Best solution by Yahoo! Answers
- What is the best way to pay a deposit when booking an apartment abroad? Paypal, Moneygram or Bank Transfer?Best solution by Yahoo! Answers
- What are the best way to go to the Bollywood?Best solution by wikihow.com
Just Added Q & A:
- How many active mobile subscribers are there in China?Best solution by Quora
- How to find the right vacation?Best solution by bookit.com
- How To Make Your Own Primer?Best solution by thekrazycouponlady.com
- How do you get the domain & range?Best solution by ChaCha
- How do you open pop up blockers?Best solution by Yahoo! Answers
For every problem there is a solution! Proved by Solucija.
-
Got an issue and looking for advice?
-
Ask Solucija to search every corner of the Web for help.
-
Get workable solutions and helpful tips in a moment.
Just ask Solucija about an issue you face and immediately get a list of ready solutions, answers and tips from other Internet users. We always provide the most suitable and complete answer to your question at the top, along with a few good alternatives below.