十年踪迹

Master the JavaScript Interview: What is a Closure?

十年踪迹 · 2016-12-23推荐 · 450阅读 CET/4 CET/6 原文链接

Master the JavaScript Interview: What is a Closure?

<figure name="81e7" id="81e7" data-scroll="native">

<canvas width="75" height="50"></canvas>

</figure>

“Master the JavaScript Interview” is a series of posts designed to prepare candidates for common questions they are likely to encounter when applying for a mid to senior-level JavaScript position. These are questions I frequently use in real interviews.

<figure name="e0ea" id="e0ea">

<iframe width="500" height="250" src="https://medium.com/media/2de2b13250440b4742682fe7c55a0ec3?postId=b2f0d2152b36" data-media-id="2de2b13250440b4742682fe7c55a0ec3" allowfullscreen="" frameborder="0"></iframe>

</figure>

<figure name="cae8" id="cae8">

<iframe width="500" height="250" src="https://medium.com/media/8e425df6095bf24396fcf9b748e81953?postId=b2f0d2152b36" data-media-id="8e425df6095bf24396fcf9b748e81953" allowfullscreen="" frameborder="0"></iframe>

</figure>

I’m launching the series with a question that is often my first and last question in my JavaScript interviews. Frankly, you can’t get very far with JavaScript without learning about closures.

You can muck around a bit, but will you really understand how to build a serious JavaScript application? Will you really understand what is going on, or how the application works? I have my doubts. Not knowing the answer to this question is a serious red flag.

Not only should you know the mechanics of what a closure is, you should know why it matters, and be able to easily answer several possible use-cases for closures.

Closures are frequently used in JavaScript for object data privacy, in event handlers and callback functions, and in partial applications, currying, and other functional programming patterns.

I don’t care if a candidate knows the word “closure” or the technical definition. I want to find out if they understand the basic mechanics. If they don’t, it’s usually a clear indicator that the developer does not have a lot of experience building actual JavaScript applications.

> If you can’t answer this question, you’re a junior developer. I don’t care how long you’ve been coding.

Be prepared for a quick follow-up: “Can you name two common uses for closures?”

What is a Closure?

In a nutshell, a closure is the combination of a function bundled together (enclosed) with references to it’s surrounding state (the lexical environment). In JavaScript, closures are created every time a function is created, at function creation time.

Those are the basic mechanics, but why do we care? In practical terms, since a closure bundles the lexical environment, a closure gives you access to an outer function’s scope from an inner function.

To use a closure, simply define a function inside another function and expose it. To expose a function, return it or pass it to another function.

The inner function will have access to the variables in the outer function scope, even after the outer function has returned.

Using Closures (Examples)

Among other things, closures are commonly used to give objects data privacy. Data privacy is an essential property that helps us program to an interface, not an implementation. This is an important concept that helps us build more robust software because implementation details are more likely to change in breaking ways than interface contracts.

> “Program to an interface, not an implementation.” > Design Patterns: Elements of Reusable Object Oriented Software

In JavaScript, closures are the primary mechanism used to enable data privacy. When you use closures for data privacy, the enclosed variables are only in scope within the containing (outer) function. You can’t get at the data from an outside scope except through the object’s privileged methods. In JavaScript, any exposed method defined within the closure scope is privileged. For example:

<figure name="bc7e" id="bc7e">

<iframe width="700" height="250" src="https://medium.com/media/9982838416a45bcb18d46764ad69ce63?postId=b2f0d2152b36" data-media-id="9982838416a45bcb18d46764ad69ce63" allowfullscreen="" frameborder="0"></iframe>

</figure>

Play with this in JSBin. (Don’t see any output? Copy and paste this HTML into the HTML pane.)

In the example above, the .get() method is defined inside the scope of getSecret(), which gives it access to any variables from getSecret(), and makes it a privileged method. In this case, the parameter, secret.

Objects are not the only way to produce data privacy. Closures can also be used to create stateful functions whose return values may be influenced by their internal state, e.g.:

const secret = (msg) =&gt; () =&gt; msg;

<figure name="8790" id="8790">

<iframe width="700" height="250" src="https://medium.com/media/adee559d0526866aadfff903258080fb?postId=b2f0d2152b36" data-media-id="adee559d0526866aadfff903258080fb" allowfullscreen="" frameborder="0"></iframe>

</figure>

Available on JSBin. (Don’t see any output? Copy and paste this HTML into the HTML pane.)

In functional programming, closures are frequently used for partial application & currying. This requires some definitions:

Application: The process of applying a function to its arguments in order to produce a return value.

Partial Application: The process of applying a function to some of its arguments. The partially applied function gets returned for later use. In other words, a function that takes a function with multiple parameters and returns a function with fewer parameters. Partial application fixes (partially applies the function to) one or more arguments inside the returned function, and the returned function takes the remaining parameters as arguments in order to complete the function application.

Partial application takes advantage of closure scope in order to fix parameters. You can write a generic function that will partially apply arguments to the target function. It will have the following signature:

partialApply(targetFunction: Function, ...fixedArgs: Any[]) =&gt;
  functionWithFewerParams(...remainingArgs: Any[])

If you need help reading the signature above, check out Rtype: Reading Function Signatures.

It will take a function that takes any number of arguments, followed by arguments we want to partially apply to the function, and returns a function that will take the remaining arguments.

An example will help. Say you have a function that adds two numbers:

const add = (a, b) =&gt; a + b;

Now you want a function that adds 10 to any number. We’ll call it add10(). The result of add10(5) should be 15. Our partialApply() function can make that happen:

const add10 = partialApply(add, 10);
add10(5);

In this example, the argument, 10 becomes a fixed parameter remembered inside the add10() closure scope.

Let’s look at a possible partialApply() implementation:

<figure name="a450" id="a450">

<iframe width="700" height="250" src="https://medium.com/media/255d8e9bf06666563615533865fde8c0?postId=b2f0d2152b36" data-media-id="255d8e9bf06666563615533865fde8c0" allowfullscreen="" frameborder="0"></iframe>

</figure>

Available on JSBin. (Don’t see any output? Copy and paste this HTML into the HTML pane.)

As you can see, it simply returns a function which retains access to the fixedArgs arguments that were passed into the partialApply() function.

Your Turn

What do you use closures for? Send me a response with your favorite use-case, examples, etc…


> Level up your skills with courses & webcasts on ES6, TDD, prototypal OO, React, & More.


Eric Elliott is the author of “Programming JavaScript Applications” (O’Reilly), and “Learn Universal JavaScript App Development with Node & React”. He has contributed to software experiences for Adobe Systems, Zumba Fitness, The Wall Street Journal, ESPN, BBC, and top recording artists including Usher,Frank Ocean, Metallica, and many more.

He spends most of his time in the San Francisco Bay Area with the most beautiful woman in the world.

相关文章