JavaScript 中的闭包(closure)是什么鬼?
2015-08-23 17:43
791 查看
什么是闭包
此文源自于 stackoverflow.com 中的一处问答:http://stackoverflow.com/questions/36636/what-is-a-closure ,有兴趣的朋友可以继续往下看。兄弟我接触 JavaScript 也好多年,自从 03年 开始有了自己的网站(早就过期了,别搜了,当时用的是免费的只有2M空间还是二级域名),虽然一直在用各种函数式编程(Functional Programming)的特性,但确实没有想过明确这些特性的定义(Definition)。今天挖出来这个概念,理解一下closure到底是什么鬼。
变量作用域(Variable scope)
When you declare a local variable, that variable has a scope. Generally local variables exist only within the block or function in which you declare them.当你声明了一个本地变量(local variables),那么它就已经有了一个作用域(scope)。一般情况下,本地变量仅存在于声明它的那个代码块或者函数中。
function() { var a = 1; console.log(a); // 好使 } console.log(a); // 没了
If I try to access a local variable, most languages will look for it in the current scope, then up through the parent scopes until they reach the root scope.
如果我想访问一个本地变量,多数编程语言将会在当前的作用域中寻找她,然后再尝试外边的(或者说上一级)那个作用域,直到到最外层(根上)的作用域为止。
var a = 1; function() { console.log(a); // 好使 } console.log(a); // 好使
When a block or function is done with, its local variables are no longer needed and are usually blown out of memory.
当一个代码块或者函数结束了,它的本地变量就不再需要了,而且会被清除出内存。
This is how we normally expect things to work.
这也是我们平时期望的那样的代码工作。
闭包是一个持续存在的本地变量作用域(A closure is a persistent local variable scope)
A closure is a persistent scope which holds on to local variables even after the code execution has moved out of that block. Languages which support closure (such as JavaScript, Swift and Ruby) will allow you to keep a reference to a scope (including its parent scopes), even after the block in which those variables were declared has finished executing, provided you keep a reference to that block or function somewhere.一个闭包是一个持续存在的作用域,它保管好了本地变量,即使运行时已经跑出了那个代码块。一些编程语言他们支持闭包(例如JavaScript, Swift 以及 Ruby),他们允许你保存一个闭包的引用(包括这个闭包的上一级、上N级作用域),即便是那个代码块声明的本地变量已经结束了运行。这些编程语言提供了保存这个引用的方法,在某个位置保管代码块活着函数。
The scope object, and all it’s local variables is tied to the function, and will persist as long as that function persists.
这个作用域对象(scope object)以及它所有的本地变量,都会被绑定到这个函数,而且一直伴随着这个函数的存在而存在。
This gives us function portability. We can expect any variables that were in scope when the function was first defined to still be in scope when we later call the function, even if we call the function in a completely different context.
这提供给了我们在函数应用上的很多便携。它使我们随后运行这个函数的时候,可以保证这个函数最初声明的本地变量会一直存在,哪怕是在别的完全不同的上下文(context)一样能使用到他们。
举例说明
Here’s a really simple example in JavaScript that illustrates the point:这有个非常简单的 JavaScript 例子,完全可以解释这一点。
outer = function() { var a = 1; var inner = function() { alert(a); } return inner; // 这里返回了一个函数 } var fnc = outer(); // 执行 outer 可以得到 inner 函数 fnc();
Here I have defined a function within a function. The inner function gains access to all the outer function’s local variables, including
a. The variable
ais in scope for the inner function.
这里我定义了一个函数中的函数(inner)。这个函数中的函数赢取了所有它外部函数的本地变量,包括
a。这个变量
a就存在于内部函数的一个作用域。
Normally when a function exits, all its local variables are blown away. However, if we return the inner function and assign it to a variable
fnc, so that it persists after
outerhas exited, all of the variables that were in scope when
innerwas defined also persist. The variable
ahas been closed over – it is within a closure.
正常情况下,当一个函数退出了,那么所有它的本地变量都会灰飞烟灭。然而,如果我们返回了这个内部函数,而且将它附给了一个变量
fnc,那么刚才的内部函数就会在
outer退出后一直存在,所有在
inner作用域内声明的变量也会一直存在。这个变量
a已经被包起来了 – 这就是闭包。
Note that the variable
ais totally private to
fnc. This is a way of creating private variables in a functional programming language such as JavaScript.
注意到变量
a相对于
fnc是完全私有的。这就是函数式编程中创建私有变量(private variables)的一种方法,例如 JavaScript。
As you might be able to guess, when I call
fnc()it alerts the value of
a, which is “1”.
正如你可能猜测,何时我会运行
fnc()来弹出变量
a的值 ‘1’ 呢?
In a language without closure, the variable
awould have been garbage collected and thrown away when the function
outerexited. Calling
fncwould have thrown an error because
ano longer exists
在一个不支持闭包的编程语言中,变量
a早就在
outer退出后被当成垃圾回收来。运行
fnc就会跑出一个错误,说是这个变量
a已经不存在了。
In JavaScript, the variable
apersists because variable scope is created when the function is first declared, and persists for as long as the function continues to exist.
在 JavaScript 中,变量
a就会一直存在,因为变量作用域已经在函数第一次声明的时候被创建出来了,而且一直被保存下来。
abelongs to the scope of
outer. The scope of
innerhas a parent pointer to the scope of
outer.
fncis a variable which points to
inner.
apersists as long as
fncpersists.
ais within the closure.
a属于
outer作用域。
inner作用域有个父指针(parent pointer)指向
outer作用域。
fnc变量指向了
inner。
a一直伴随着
fnc的存在而存在。
a就是在传说中的闭包之中。
相关文章推荐
- javascript对象
- JSP 笔记
- js算法:分治法-归并排序
- JavaScript——关于画布元素canvas的使用
- JSON详解
- BackboneJS入门学习[01]---预热
- JS的HTML DOM disabled 属性
- javascript 如何访问 action或者controller 传给 jsp 页面的值
- 【js】JSON.stringify 语法实例讲解
- jsp基础语法
- JavaScript添加事件
- [LeetCode][JavaScript]Course Schedule II
- JSON.parse()和JSON.stringify()
- javascript活动
- [LeetCode][JavaScript]Course Schedule
- JS的一些笔记
- js笔试题
- 【JavaScript基础知识】——数据类型与typeof操作符
- JavaScript高级
- JavaScript表单验证