Closures in JavaScript
2015-06-09 17:18
851 查看
By now, you probably know all about functions and all the fun functiony things that they do. An important part of working with functions, with JavaScript, and (possibly) life in general is understanding the topic known as closures. Closures touch upon a gray area where functions and variable scope intersect:
Now, I am not going to say any more about closures, for this is something best explained by seeing code. Any words I add right now to define or describe what closures are will only serve to confuse things. In the following sections, we'll start off in familiar territory and then slowly venture into hostile areas where closures can be found.
Onwards!
Functions within Functions
The first thing we are going to do is really drill in on what happens when you have functions within functions...and the inner function gets returned. As part of that, let's do a quick review of functions.Take a look at the following code:
After this code has run, the roomArea variable contains the result of multiplying 10 and 10...which is simply 100:
As you know, what a function returns can pretty much be anything. In this case, we returned a number. You can very easily return some text (aka a String), the undefined value, a custom object, etc. As long as the code that is calling the function knows what to do with what the function returns, you can do pretty much whatever you want. You can even return another function. Let me rathole on this a bit.
Below is a very simple example of what I am talking about:
The interesting part is what the youSayGoodBye function returns when it gets called. It returns theandISayHello function:
As part of running to completion, the andISayHello function will be created and then returned as well. At this point, your something variable only has eyes for one thing, and that thing is the andISayHellofunction:
The youSayGoodBye outer function, from the something variable's point of view, simply goes away. Because the something variable now points to a function, you can invoke this function by just calling it using the open and close parentheses like you normally would:
All of this should be pretty straightforward and probably a review. The only thing that you may have found new is realizing once a function returns a value, it is no longer around. The only thing that remains is the returned value.
Ok, we are getting close to the promised hostile territory. In the next section, we will extend what we've just seen by taking a look at another example with a slight twist.
When the Inner Functions Aren't Self-Contained
In the previous example, your andISayHello inner function was self-contained and didn't rely on any variables or state from the outer function:Getting back to the outer stopWatch function, the last thing that happens is that it returns the getDelayfunction before exiting. As you can see, the code you see here is very similar to the earlier example. You have an outer function, you have an inner function, and you have the outer function returning the inner function.
Now, to see the stopWatch function at work, add the following lines of code:
Basically, you have a stopwatch that you invoke, run some long-running operation, and invoke again to see how long the long-running operation took place.
Now that you can see our little stopwatch example working, let's go back to the stopWatch function and see what exactly is going on. Like I mentioned a few lines ago, a lot of what you see is similar to theyouSayGoodBye / andISayHello example. There is a twist that makes this example different, and the important part to note is what happens when the getDelay function is returned to the timer variable.
Here is an incomplete visualization of what this looks like:
The stopWatch outer function is no longer in play, and the timer variable is bound to the getDelayfunction. Now, here is the twist. The getDelay function relies on the startTime variable that lives in the context of the outer stopWatch function:
The JavaScript runtime that keeps track of all of your variables, memory usage, references, and so on is really clever. In this example, it detects that the inner function (getDelay) is relying on variables from the outer function (stopWatch). When that happens, the runtime ensures that any variables in the outer function that are needed are still available to the inner function even if the outer function goes away.
To visualize this properly, here is what the timer variable looks like:
It is still referring to the getDelay function, but the getDelay function also has access to the startTimevariable that existed in the outer stopWatch function. This inner function, because it enclosed relevant variables from the outer function into its bubble (aka scope), is known as a closure:
To define the closure more formally, it is a newly created function that also contains its variable context:
To review this one more time using our existing example, the startTime variable gets the value ofDate.now the moment the timer variable gets initialized and the stopWatch function runs. When thestopWatch function returns the inner getDelay function, the stopWatch function goes away. What doesn't go away are any shared variables inside stopWatch that the inner function relies on. Those shared variables are not destroyed. Instead, they are enclosed by the inner function aka the closure.
Wrapping up Closures
By looking at closures through examples first, you really missed out on a lot of boring definitions, theories, and hand waving. In all seriousness, closures are very common in JavaScript. You will encounter them in many subtle and not-so-subtle ways:If there is only thing you take out of all of this, remember the following: The most important thing closures do is allow functions to keep on working even if their environment drastically changes or disappears. Any variables that were in scope when the function was created are enclosed and protected to ensure the function still works. This behavior is essential for a very dynamic language like JavaScript where you often create, modify, and destroy things on the fly. Yay!
Did You Like This?
MORE INFOBUY NOW
Getting Help
If you have questions, need some assistance on this topic, or just want to chat - post in the commentsbelow or drop by our friendly forums (where you have a lot more formatting options) and post your question. There are a lot of knowledgeable and witty people who would be happy to help you out相关文章推荐
- 测试驱动开发(TDD)及测试框架Mocha.js入门学习
- js内存泄露的几种情况详细探讨
- JSOI2015 分组赛记
- JSP/SERVLET入门教程--Servlet 使用入门
- JavaScript内存优化
- PHP和javascript中使用正则表达式匹配中文字符串
- Chrome新版JS调试工具
- Javascript关于JSON集合的几种循环方法
- 编写高性能JavaScript In JavaScript
- 【译】国外优秀JavaScript资源推荐
- JavaScript、js数组的基本操作
- ios7 JavaScriptCore.framework
- JS合并的必要性分析
- servlet+jsp 实现一个简单的web项目
- 相对路径、绝对路径、部署路径(html/css/servlet/jsp)
- 我所了解的javaScript细节
- JSP放入Jar包支持
- js简单的贪吃蛇小游戏
- 这些年,我收集的JavaScript代码(一)
- JSP基本用法(二)隐含对象