Heim  >  Artikel  >  Backend-Entwicklung  >  如何通俗地解释闭包的概念?

如何通俗地解释闭包的概念?

WBOY
WBOYOriginal
2016-06-06 16:22:441296Durchsuche

网上随便搜一个闭包的解释,动不动就长篇大论,各种专业名词,又扯上了内存泄露,各种用法……
我不想了解那么多没用的,能不能简单的告诉到底什么是闭包,我不关心闭包怎么就不能被销毁,怎么个指针指来指去的,看得我是越看头越晕!!
我得理解就是:
(函数里面有个局部变量,然后通过在把这个变量的值retrun给函数)
这个过程就是闭包特性了。这个用法是不是太常见了啊。。。怎么那么多大牛能写出来那么长的文章来

回复内容:

假设你现在有一个函数 f (x) = a + x

这个函数是不完整的,比如 f (1) = a + 1 你还差一个问题: a 是多少?

有两个方法回答这个问题

第一种叫“动态作用域”,a的值决定于函数调用时上下文中a的值,比如

a = 1;
v=f(1) ; 这里v为2

动态作用域的问题是,函数每一次调用相同的参数未必返回相同的值,其返回值还取决于上下文的某些值

第二种是“词法作用域”,a的值取决于函数定义时上下文中的值

g (a) = lambda (x) a + x;
f = g(2)

这里函数g返回一个和上面函数f形式一样函数,a在此处为2,那么执行

a = 1;
v=f(1) ;这里v为3

因为f要“记住”自己定义时a的值为2,所以实现时

f (x) = a + x 和 a = 2 被打包在一块,被称为“闭包”,意思是它是完整独立的,仅仅依靠调用时参数求值,不再依赖调用时的上下文

晕,写完以后才发现我也写了不少... 可以这样理解,因为『纯』的函数是没有状态的,加入了闭包以后就变成有状态的了,相对于一个有成员变量的类实例来说,闭包中的状态值不是自己管理,可以认为是『上帝』在管理。

看下面这个 javascript 例子:
<code class="language-text">var counter = function() {
	var counter = 0
	return function() {
		return counter++
	}
}

var anotherCounter = counter()
console.log(anotherCounter())
console.log(anotherCounter())
console.log(anotherCounter())
</code>
片面地讲 闭包就是 “北京城”,一层一层的控制,皇宫的皇上看上城内的妹子就可以用,城内的汉子要么用城内的妹子,要么去城外 =。= 把数据和作用域绑定到一起就是闭包。 可以学习下做下面几道题:Learning Advanced JavaScript 通过引用变量从而阻止该变量被垃圾回收的机制 将一个上下文的私有变量的生命周期延长的机制 搬运一下 @winter 的blog 闭包概念考证 · Issue #3 · wintercn/blog · GitHub
<code class="language-js"><span class="c1">// One of JavaScript's most powerful features is closures. If a function is</span>
<span class="c1">// defined inside another function, the inner function has access to all the</span>
<span class="c1">// outer function's variables, even after the outer function exits.</span>
<span class="kd">function</span> <span class="nx">sayHelloInFiveSeconds</span><span class="p">(</span><span class="nx">name</span><span class="p">){</span>
    <span class="kd">var</span> <span class="nx">prompt</span> <span class="o">=</span> <span class="s2">"Hello, "</span> <span class="o">+</span> <span class="nx">name</span> <span class="o">+</span> <span class="s2">"!"</span><span class="p">;</span>
    <span class="c1">// Inner functions are put in the local scope by default, as if they were</span>
    <span class="c1">// declared with `var`.</span>
    <span class="kd">function</span> <span class="nx">inner</span><span class="p">(){</span>
        <span class="nx">alert</span><span class="p">(</span><span class="nx">prompt</span><span class="p">);</span>
    <span class="p">}</span>
    <span class="nx">setTimeout</span><span class="p">(</span><span class="nx">inner</span><span class="p">,</span> <span class="mi">5000</span><span class="p">);</span>
    <span class="c1">// setTimeout is asynchronous, so the sayHelloInFiveSeconds function will</span>
    <span class="c1">// exit immediately, and setTimeout will call inner afterwards. However,</span>
    <span class="c1">// because inner is "closed over" sayHelloInFiveSeconds, inner still has</span>
    <span class="c1">// access to the `prompt` variable when it is finally called.</span>
<span class="p">}</span>
<span class="nx">sayHelloInFiveSeconds</span><span class="p">(</span><span class="s2">"Adam"</span><span class="p">);</span> <span class="c1">// will open a popup with "Hello, Adam!" in 5s</span>
</code>
<code class="language-js"><span class="kd">var</span> <span class="nx">globalVal</span><span class="o">=</span><span class="kc">null</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">fn</span><span class="o">=</span><span class="kd">function</span><span class="p">(){</span>
	<span class="kd">var</span> <span class="nx">a</span><span class="o">=</span><span class="mi">1</span><span class="p">;</span>
	<span class="nx">globalVal</span><span class="o">=</span><span class="kd">function</span><span class="p">(){</span>
		<span class="nx">a</span><span class="o">++</span><span class="p">;</span>
		<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">a</span><span class="p">);</span>
	<span class="p">}</span>
<span class="p">}</span>

<span class="nx">fn</span><span class="p">();</span>
<span class="nx">globalVal</span><span class="p">();</span><span class="c1">//2</span>
<span class="nx">globalVal</span><span class="p">();</span><span class="c1">//3</span>
</code>
Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn