miaoYu

miaoYu正在翻译

Understanding JavaScript: Closures – Hacker Noon

原文链接: hackernoon.com

Due to the amazing quantity of libraries, tools and all kinds of things that make your development easier, a lot of programmers start building applications without having the deep understanding of how something works under the hood. JavaScript is the poster boy of this exact behavior. While it is one of the most complicated languages and most widely spread, many developers are attracted to using higher level tools and abstracting away the “bad parts” of the language.

While you will still be able to do build amazing applications doing that, going into the JavaScript maelstrom can be quite beneficial to you. Understanding the “weird parts” is what separates the average grunt coder from the senior developer and while the JS ecosystem is ever-changing, the fundamentals are those on top of which all other tools are built. Understanding those gives you a broader perception and changes the way you look at the development process.

I’m far from an expert in this field, but I believe in sharing knowledge and information and also that by explaining something helps me understand it better. I’ll be writing a small series of posts on major JS topics, starting with one of the most commonly used things in JavaScript — Closures.

Whats a Closure?

Closures are nothing special, but they require deeper understanding in order to use properly. If you’ve ever made an AJAX request, or an event handler you have already used closures, but probably don’t know that they are called like that. Even though, they can be described as a “stateful function”, the most precise definition I’ve ever encountered is given by Kyle Simpson:

Closure is when a function is able to remember and access its lexical scope even when that function is executing outside its lexical scope.

Okay, actually this can be a bit overwhelming. In JavaScript, functions create a new scope, therefore another explanation for closures is that they are exposed functions contained inside another function. Even though they are not called inside the wrapping function, they still have access to it’s scope. Probably an example will illustrate that better:

<IFRAME width="700" height="250" src="/media/27931ea38f61ee286a6d96cd243de880?postId=4188edf5ea1b" data-media-id="27931ea38f61ee286a6d96cd243de880" data-thumbnail="https://i.embed.ly/1/image?url=https%3A%2F%2Favatars3.githubusercontent.com%2Fu%2F7038691%3Fv%3D3%26s%3D400&key=4fce0568f2ce49e8b54624ef71a8a5bd" allowfullscreen frameborder="0"></IFRAME>

In this example you see that we define a person() function that takes a name as a parameter. It returns the greet() function which can use that name even though it’s not explicitly defined in it’s scope — it accesses it from the parent scope. Even though we call it after calling the parent function, it can still access the name and prints the expected result, because greet() is a closure.

As I said, you’ve probably done something like that without really understanding what’s going on. It’s just one of those JS features that you take for granted and don’t pay extra attention to it. Closures are mainly used for providing data privacy. By explicitly returning those functions we define a public API for our function and allow everything else to remain hidden behind the curtain. However, it’s important to realize that closures are functions. If in the above example we had returned a key — value object, this would not have been a closure.

Modules

<IFRAME width="700" height="250" src="/media/bbaa072f1dd74d9133707b7e3ac2514d?postId=4188edf5ea1b" data-media-id="bbaa072f1dd74d9133707b7e3ac2514d" data-thumbnail="https://i.embed.ly/1/image?url=https%3A%2F%2Favatars3.githubusercontent.com%2Fu%2F7038691%3Fv%3D3%26s%3D400&key=4fce0568f2ce49e8b54624ef71a8a5bd" allowfullscreen frameborder="0"></IFRAME>

Now that you’re familiar with closures, here’s a similar example. In JavaScript, this particular pattern is called a module. Only by calling the Person function, we can create an instance of the module, the inner scope and the closures. After creating it, an object is returned which has a reference to the publicly exposed functions, but not to the private ones (those that are not exposed). This is one of the most widely used patterns in JavaScript.

If you’re familiar with ES6, you have probably seen the new modules that are file-based and use the import and export keywords.

// person.js
const name = 'Alex Kondov';

const getName = () => {

return name;

}

// app.js
import getName from 'person'

console.log(getName());

This is the modern way to do modules. Even though this is a pretty dumb example you probably get the idea — you export only what you want to be public, leaving everything else hidden. There’s nothing special in the ES6 way of doing it, it’s just syntactic sugar over the regular modules.

Weird parts

You probably feel confident about your closure knowledge so far, but as with everything else in JavaScript, there’s always a catch. If not used properly, closures can cause a lot of headache. Take this simple code as an example:

for (var i=1; i<=5; i++) {
setTimeout( function timer(){
console.log( i );
}, i*1000 );
}

All we’re doing here is looping from 1 do 5 and setting a timeout to print the number after a certain amount of time. You probably expect that to return 1, 2, 3, 4 and 5, right? Wrong! You’ll be surprised that you’ll get 6 logged 5 times in the console. You expect that every setTimeout() receives it’s own copy of the i variable but it doesn’t. It accesses it from the parent scope and when it comes the time to log the variable in the console, the loop has already passed and the value of i is 6.

I won’t go into details here because I may cause more confusion than clarity, but if you want to go deeper and develop your JavaScript knowledge about closures you should see Kyle Simpson’s book — You don’t know JS. Here’s the chapter about scope and closures: https://github.com/getify/You-Dont-Know-JS/blob/master/scope%20%26%20closures/ch5.md

Thank you for the read and hope it was helpful. Check out my profile for other JS related posts.

Understanding JavaScript
Scope: https://medium.com/@KondovAlexander/understanding-javascript-scope-1d4a74adcdf5

Closures: https://medium.com/@KondovAlexander/understanding-javascript-closures-4188edf5ea1b

Prototype and Inheritance: https://hackernoon.com/understanding-javascript-prototype-and-inheritance-d55a9a23bde2

The this keyword: https://medium.com/@KondovAlexander/understanding-javascript-the-this-keyword-4de325d77f68

The new keyword: https://medium.com/@KondovAlexander/understanding-javascript-new-keyword-ec67c8caaa74

Coercion: https://medium.com/@KondovAlexander/understanding-js-coercion-ff5684475bfc

The Event Loop_:_ https://medium.com/@KondovAlexander/understanding-js-the-event-loop-959beae3ac40

[

](http://bit.ly/HackernoonFB)

[

](https://goo.gl/k7XYbx)

[

](https://goo.gl/4ofytp)

Hacker Noon is how hackers start their afternoons. We’re a part of the @AMI family. We are now accepting submissions and happy to discuss advertising & sponsorship opportunities.

If you enjoyed this story, we recommend reading our latest tech stories and trending tech stories. Until next time, don’t take the realities of the world for granted!