Javascript进阶(5)---闭包

  维基:

  在计算机中,闭包(也称词法闭包或者函数闭包),是指一个函数或者函数的引用,与一个引用环境绑定在一起。这个引用环境是一个存储该函数每个非局部变量的表。

  百度百科:                                                          

    闭包是指可以包含自由(未绑定到特定对象)变量的代码块;这些变量不是在这个代码块内或者任何全局上下文中定义的,而是在定义代码块的环境中定义(局部变量)。“闭包” 一词来源于以下两者的结合:要执行的代码块(由于自由变量被包含在代码块中,这些自由变量以及它们引用的对象没有被释放)和为自由变量提供绑定的计算环境(作用域)


  1. 一个简单的例子 

    function outer(){
      var localVal = 30;
      return function(){
        return  localVal;
        }
      }
    var func = outer ();
    func();  //调用func()函数,得到30

    在outer()函数被调用之后,localVal未被释放,匿名函数执行的时候,仍能够调用外函数outer()中的localVal变量。(这就是一个简单的闭包)

  2. 闭包的优缺点
    • 优点:灵活方便、可进行封装
    • 不及时释放会造成是空间上的浪费、会造成内存泄漏、会造成性能上的消耗
  3. 其他例子

     1 function count(){
     2     var arr = [];
     3     for (var i = 1; i<=3; i++){
     4       arr.push(function(){
     5         return i*i;
     6       });
     7     }
     8   return arr;
     9   }
    10 var results = count();
    11 var res1=results[0];
    12 var res2=results[1];
    13 var res3=results[2];
    14
    15 console.log(res1+"\n"+res2+"\n"+res3);
    16 /*function (){
    17         return i*i;
    18       }
    19 function (){
    20         return i*i;
    21       }
    22 function (){
    23         return i*i;
    24       }
    25 */
    • 注意在代码第4行中,push进数组的是匿名函数function函数体原封不动地放进了数组,变量 i 也没有进行取值运算
console.log(res1()+"\n"+res2()+"\n"+res3());/*16  16  16 */
    •   因为在 “var results = count();” 执行之后,for 循环中的 i 值已经变为 4 ,现在调用,返回 i * i 的值自然是16
  • 如果想返回我们“原本期望的值“1 4 9”的话,我们尝试做出小的改动  
  • 1 function count(){
    2     var arr = [];
    3     for (var i = 1; i<=3; i++){
    4       arr.push(function(n){
    5         return function(){
    6            return n*n;
    7           }
    8         }(i));                //关键点在此处
    9     }
    10   return arr;
    11   }
    12 var results = count();
    13 var res1=results[0];
    14 var res2=results[1];
    15 var res3=results[2];
    16
    17 console.log(res1+"\n"+res2+"\n"+res3);
    18 /*function (){
    19         return i*i;
    20       }
    21 function (){
    22         return i*i;
    23       }
    24 function (){
    25         return i*i;
    26       }
    27 */
    28 console.log(res1()+"\n"+res2()+"\n"+res3());/* 1 4 9*/
  • 我们再返回一个函数的同时使用“()”符号将函数就地执行了,这个要才能够保证内部函数中的 i * i 返回的是当次循环的的 i 值。

  4、其他笔记

  • 因为Javscript不算是一门面对现对象的语言,所以无法直接封装私有变量,但利用闭包,我们可以模拟这个过程。
  • 1 function create_sth(initial){
    2     var x = initial || 0 ;
    3     return {
    4       inc : function (){
    5         x + = 1;
    6           return x;  //返回的对象中包含着inc函数,该函数又携带着一个局部变量x。
    7       }
    8     }
    9   }
  • 换句话说,闭包就是携带状态的函数,并且它的状态可以对外界完全隐藏起来。

  

  

时间: 2024-10-08 06:46:01

Javascript进阶(5)---闭包的相关文章

javascript进阶笔记(2)

js是一门函数式语言,因为js的强大威力依赖于是否将其作为函数式语言进行使用.在js中,我们通常要大量使用函数式编程风格.函数式编程专注于:少而精.通常无副作用.将函数作为程序代码的基础构件块. 在函数式编程中,有一种函数称为匿名函数,也就是没有名称的函数,是js中的一个非常重要的概念.通常匿名函数的使用情况是,创建一个供以后使用的函数.比如将匿名函数保存在一个变量里面,或将其作为一个对象方法,更有甚者将其作为一个回调等等之类的. //保存在变量中,通过fn去引用 var fn=function

JavaScript进阶系列06,事件委托

在"JavaScript进阶系列05,事件的执行时机, 使用addEventListener为元素同时注册多个事件,事件参数"中已经有了一个跨浏览器的事件处理机制.现在需要使用这个事件处理机制为页面元素注册事件方法. □ 点击页面任何部分触发事件 创建一个script1.js文件. (function() { eventUtility.addEvent(document, "click", function(evt) { alert('hello'); }); }(

JavaScript进阶系列02,函数作为参数以及在数组中的应用

有时候,把函数作为参数可以让代码更简洁. var calculator = { calculate: function(x, y, fn) { return fn(x, y); } }; var sum = function(x, y) { return x + y; }, diff = function (x, y) { return x - y; }; var sumResult = calculator.calculate(2, 1, sum), diffResult = calculat

JavaScript进阶系列07,鼠标事件

鼠标事件有Keydown, Keyup, Keypress,但Keypress与Keydown和Keyup不同,如果按ctrl, shift, caps lock......等修饰键,不会触发Keypress事件,而会触发Keydown和Keyup事件,这就是Keypress事件与Keydown.Keyup事件的不同之处.另外,通常使用Keypress事件来获取用户输入信息. 继续使用"JavaScript进阶系列05,事件的执行时机, 使用addEventListener为元素同时注册多个事件

JavaScript进阶系列04,函数参数个数不确定情况下的解决方案

本篇主要体验函数参数个数不确定情况下的一个解决方案.先来看一段使用函数作为参数进行计算的实例. var calculate = function(x, y, fn) { return fn(x, y); }; var sum = function(x, y) { return x + y; }; var diff = function(x, y) { return x - y; }; var sumResult = calculate(1, 2, sum), diffResult = calcu

JavaScript进阶系列05,事件的执行时机, 使用addEventListener为元素同时注册多个事件,事件参数

本篇体验JavaScript事件的基本面,包括: ■ 事件必须在页面元素加载之后起效■ 点击事件的一个简单例子■ 为元素注册多个点击事件■ 获取事件参数 □ 事件必须在页面元素加载之后起效 有这样一段简单的代码: <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> <title></title> <style>

JavaScript进阶系列03,通过硬编码、工厂模式、构造函数创建JavaScript对象

本篇体验通过硬编码.工厂模式.构造函数来创建JavaScript对象. □ 通过硬编码创建JavaScript对象 当需要创建一个JavaScript对象时,我们可能这样写: var person = { firstName: "Darren", lastName: "Ji", getFullName: function() { return this.firstName + " " + this.lastName; } }; 如果需要创建2个结

Javascript 进阶 作用域 作用域链

转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/25076713 一直觉得Js很强大,由于长期不写js代码,最近刚好温故温故. 1.Javascript没有代码块作用域的概念,局部作用域是针对函数来说的. function fun() { for( var i = 0 ; i < 10 ; i++) {} //如果在Java中i此时应当属于未声明的变量,但是Js中i的作用域依然存在 console.log(i);//10 if(

深入理解javascript原型和闭包(15)——闭包

http://www.cnblogs.com/wangfupeng1988/p/3994065.html 深入理解javascript原型和闭包(15)——闭包