zoukankan      html  css  js  c++  java
  • 如何理解javascript closure ?

      接触过javascript的人应该听过闭包(closure),有一种观点认为是闭包赋予了javascript的强大能力,也赋予了它具备OOP的特征。既然javascript closure如此重要,那么问题来了,什么是closure呢?closure有什么作用?本文将结合我自己对closure的理解,用尽量通俗易懂的方式来进行阐述。

      先看看老外对closure怎么定义的?A closure is an inner function that has access to the outer (enclosing) function's variables—scope chain.从字面上来看,可以翻译为:闭包就是一个内部函数,它具备访问外部函数变量(这些变量位于作用域链中)的能力[注意变量不包含this和arguments]。但这个概念还是过于“专业化”, 不接地气,只从概念上来看,非常抽象。下面用一段JS来对应解释闭包的概念:


    个人理解为:fInner函数定义在fOuter的内部,可以访问fOuter定义的变量,这个fInner函数就是closureclosure的 scope chain有3个一个是fInner函数定义的变量;一个是外部fOuter的变量;还有一个是全局变量(global variables)。closure的作用可以保留变量的值换句话说,函数fInner就是一个closure

      closure可以干2件事情:

      1)closure可以调用(闭包存储的外部变量是引用而不是值,这点非常重要)在当前函数以外的定义的变量(即使外部函数已经返回);

      2)closure可以修改外部定义的变量值

    下面通过一段JS代码来阐述为什么闭包存储的外部变量是引用而不是值,这点非常重要

     

     1     function mixFunction(a)
     2     {
     3         var result=[],i,n;
     4         n=a.length;
     5         for(i=0;i<n;i++){
     6             result[i]=function(){
     7                 //Closure对外部变量是引用
     8                 console.log("for i="+i);
     9                 return a[i];//a[i-1]
    10             }
    11         }
    12         return result;
    13     }
    14     var mixcall=mixFunction([10,20,30]);
    15     var f=mixcall[0];
    16     console.log(f());//?应该输出什么值

     

    f()会输出 10 么?答案是undefined!!!

    为什么是这样的呢? 因为闭包对i是引用,在for循环时,会不断更新i的值。即在调用f()后,i已经被修改为3 (i===3),而a[3]为undefined!!

    上述的代码始终会输出a[2]的值,也就是30。

     那么问题来了?怎么解决该问题呢?这就要用到JS中的IIFE技术啦!IIFE技术来解决JS缺少块级作用域的解决方案如下代码所示:

     1     function mixFunctionFix(a)
     2     {
     3         var result=[],i,n;
     4         n=a.length;
     5         for(i=0;i<n;i++){
     6             //IIFE技术来解决JS缺少块级作用域的解决方案
     7             (function(j){
     8                 result[i]=function(){
     9                     //Closure对外部变量是引用
    10                     console.log("for j="+j);
    11                     return a[j];
    12                 }
    13             })(i)
    14         }
    15         return result;
    16     }
    17     var mixcall=mixFunctionFix([10,20,30]);
    18     var f=mixcall[0];
    19     console.log(f());//10

     前面提到JS闭包可以实现OOP的特征,下面给出JS如何定义一个“User类”(实际是一个JS函数)。此函数有私用变量和方法,同时也具有公开的方法。私有变量和方法不能函数外部调用:

     1     function User(){
     2         //private properties
     3         var _name = '';
     4         var _age  = 0;
     5      
     6         //private method
     7         function privateMethod(){
     8             return "private  Method"
     9         };
    10         //public method
    11         this.setName = function(name){
    12             //can call
    13             privateMethod();
    14             _name = name;
    15             return this;
    16         };
    17      
    18         this.setAge = function(age){
    19             _age = age;
    20             return this;
    21         };
    22         this.getAge = function(){
    23             return _age;
    24         };
    25         this.getName = function(){
    26             return _name;
    27         };
    28     }
    29     var p=new User();
    30     console.log(p.setName('jackwang').setAge(28));
    31     console.log(p.getName());//jackwang
    32     console.log(p.getAge());//28
    33     console.log(p._name);//undefined 
    34     console.log(p.privateMethod());//error

    私有变量_name和_age以及私有方法privateMethod()都不能在函数外部调用。User设置name和age只能通过公开方法setName和setAge进行,获取只能通过getName和getAge进行访问。

    有人会问,这个是闭包么?看下图:

  • 相关阅读:
    New version of VS2005 extensions for SharePoint 3.0
    QuickPart : 用户控件包装器 for SharePoint Server 2007
    随想
    发布 SharePoint Server 2007 Starter Page
    如何在SharePoint Server中整合其他应用系统?
    Office SharePoint Server 2007 中文180天评估版到货!
    RMS 1.0 SP2
    SharePoint Server 2007 Web内容管理中的几个关键概念
    如何为已存在的SharePoint站点启用SSL
    Some update information about Office 2007
  • 原文地址:https://www.cnblogs.com/isaboy/p/javascript_closure.html
Copyright © 2011-2022 走看看