IT技术博客大学习 共学习 共进步

浅谈javascript闭包

前端码工 2016-03-21 23:57:20 浏览 2,222 次

   要成为高级 JavaScript 程序员,就必须理解闭包。

   闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现。

   闭包是一个很好的面试题目,能够很好的考查出不同水平的面试者。

   看吧,上面说的,赶紧把闭包好好理一下吧。好的,现在开始。

   概念:

   闭包是可以包含自由(未绑定)变量的代码块;
这些变量不是在这个代码块或者任何全局上下文中定义的,而是在定义代码块的环境中定义。
“闭包” 一词来源于以下两者的结合:要执行的代码块(由于自由变量的存在,相关变量引用没有释放)和为自由变量提供绑定的计算环境(作用域)。
闭包的价值在于可以作为函数对象或者匿名函数。

   闭包是指有权访问另一个函数作用域中的变量的函数。创建闭包的常见方式,就是在一个函数内部创建另一个函数。

   除了javascript,在 Scheme、Common Lisp、Smalltalk、Groovy、Ruby 和 Python 等语言中都能找到对闭包不同程度的支持。

   在《JavaScript高级程序设计》一书中,闭包是在匿名函数这一章引出来的。其实最常见的闭包 (Closure)形式就是:

[javascript][/javascript]
(function(){
    //do something
})();

   对,匿名函数。为什么是一个闭包呢,可以给这个闭包传入一个参数。

[javascript][/javascript]
(function(t){
    //do something
})(time);

   里面的t就指向 time了。

   变量的作用域

   首先来了解一下变量的作用域吧

[javascript][/javascript]
var num = 999;
 
function displayNum(){
    var num1 = 888;
    alert(num);
}
 
displayNum();//999
 
alert(num1)//error

   JavaScript中,函数内部可以读取全局的变量,而函数外面是读取不到函数内部的变量的。

[javascript][/javascript]
function displayName(preTitle){
    return function(name){
        return preTitle+":"+name;
    }
}
displayName("name")("welpher");

   这段代码中,里面的匿名函数,访问了外部函数的变量preTitle。即使这个内部函数被返回了,而且是在其它地方被调用了,它还是可以访问变量preTitle。因为内部函数的作用域链中包含displayName()的作用域。(当某个函数第一次被调用时,会创建一个执行环境(execution context)及相应的作用域链,并把作用域链赋给一个特殊的内部属性([[Scope]])。然后,使用this、arguments和其它命名参数的值来初始化函数的活动对象(activation object)。但是在作用域链中,外部函数的活动对象始终处于第二位,外部的外部函数的活动对象处于第三位,直至作为作用域链终点的全局执行环境)

   参考:

   1、《JavaScript高级程序设计》(第二版)

   2、http://www.ruanyifeng.com/blog/2009/08/learning_javascript_closures.html

建议继续学习

  1. for 循环为何可恨? (阅读 5,383)
  2. 理解Javascript的闭包 (阅读 4,749)
  3. GC与JS内存泄露 (阅读 4,604)
  4. JavaScript的闭包问题 (阅读 4,305)
  5. 在回调和闭包中的内存泄漏 (阅读 3,983)
  6. 闭包漫谈(从抽象代数及函数式编程角度) (阅读 3,783)
  7. 什么是闭包(Closure)? (阅读 3,764)
  8. 闭包与作用域 (阅读 3,722)
  9. 闭包漫谈(从抽象代数及函数式编程角度) (阅读 3,725)
  10. 前端代码之丑(一):分支化技巧 (阅读 3,542)