Leo Wang's Notepad

我对Javascript中的闭包Closure的理解

怎样理解 Javascript Closure 也就是闭包的概念,想必很多人在为此头疼。

笔者先后参考了下面这些资料

MDN Javascript Closure https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Closures

阮一峰的博客 http://www.ruanyifeng.com/blog/2009/08/learning_javascript_closures.html

Frank Fang的博客 http://www.cnblogs.com/frankfang/archive/2011/08/03/2125663.html

作者们都声称自己搞懂了闭包的概念,可自己还是看的云里雾里。

直到笔者看到下面这篇文章,才开始真正理解闭包的概念和应用场景。

Jonathan D. Johnson的博客 http://jondavidjohn.com/javascript-closure-explained-using-events/

下面我试着把这篇文章边翻译边把自己的理解写出来。

先看一下下面这段程序,

效果:在第3次按下button的时候显示”Third time’s the charm”的消息框。

// declare counter outside event handler's scope
var counter = 0;
var element = document.getElementById("button");

element.onclick = function() {
    // increment outside counter
    counter++;

    if (counter === 3) {
        // do something every third time
        alert("Third time's the charm!");
        // reset counter
        counter = 0;
    }
};

程序中声明了一个全局变量counter,每次按下button都会唤起程序,从而让counter++

如果你只在自己的网页中执行一次的话,这么写也无所谓,但是如果你想在其他地方复用的话,

最好还是把这段程序封装成单独的一个函数。

这时问题就来了,你要每次都声明一个外部的全局变量counter吗?很明显这种做法太笨拙。

于是closure的作用就发挥出来了。

如果你看过了MDN的解释,就会知道closure其实是这样一种机制,

函数可以访问它被创建时所处的作用域中的对象(Object)。

于是上面那段程序利用闭包可以优化成下面这种形式:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<input type="submit" id="button1" value="button1" class="button"/>
<input type="submit" id="button2" value="button2" class="button"/>

<script>
    var myClosureFunc = function () {
        // init the count to 0
        var count = 0;
        return function (e) {
            //count
            count++;

            if (count === 3) {
                // do something every third time
                alert("Third time's the charm!");
                //reset counter
                count = 0;
            }
        };
    }

    var element1 = document.getElementById("button1");
    element1.onclick = myClosureFunc();

    var element2 = document.getElementById("button2");
    element2.onclick = myClosureFunc();
</script>


</body>
</html>

 

counter的位置移到了event handler函数的内部,而函数的返回值为一个闭包。

按照上面的概念,myClosureFunc中的闭包可以访问它创建时所处的作用域(scope),

于是它就可以访问自己的counter,而这个counter是相对全局的,也就是说,在element1被按下的过程中,这个counter是共有的。

而element1和element2中的counter又是相对独立的。

怎么样,有没有帮你理解closure在作用域这个概念里所起的作用?

 

 

 

Tagged on:

发表评论

电子邮件地址不会被公开。 必填项已用*标注