闭包 订阅
闭包就是能够读取其他函数内部变量的函数。例如在javascript中,只有函数内部的子函数才能读取局部变量,所以闭包可以理解成“定义在一个函数内部的函数“。在本质上,闭包是将函数内部和函数外部连接起来的桥梁。 [1] 展开全文
闭包就是能够读取其他函数内部变量的函数。例如在javascript中,只有函数内部的子函数才能读取局部变量,所以闭包可以理解成“定义在一个函数内部的函数“。在本质上,闭包是将函数内部和函数外部连接起来的桥梁。 [1]
信息
相关学科
离散数学
特    点
未绑定到特定对象
本    质
将函数内部和外部连接起来的桥梁
用    途
编程逻辑
中文名
闭包
外文名
closure
闭包简单介绍
闭包包含自由(未绑定到特定对象)变量,这些变量不是在这个代码块内或者任何全局上下文中定义的,而是在定义代码块的环境中定义(局部变量)。“闭包” 一词来源于以下两者的结合:要执行的代码块(由于自由变量被包含在代码块中,这些自由变量以及它们引用的对象没有被释放)和为自由变量提供绑定的计算环境(作用域)。在PHP、Scala、Scheme、Common Lisp、Smalltalk、Groovy、JavaScript、Ruby、 Python、Go、Lua、objective c、swift 以及Java(Java8及以上)等语言中都能找到对闭包不同程度的支持。
收起全文
精华内容
参与话题
问答
  • JS闭包的理解

    万次阅读 多人点赞 2019-05-14 19:49:11
    闭包的简介: 闭包就是能够读取其他函数内部变量的函数。只有函数内部的子函数才能读取局部变量,在本质上,闭包是函数内部和函数外部连接起来的桥梁。 闭包的定义: 如果在一个内部函数里,对在外部作用域(但不是...

    闭包的简介:

    闭包就是能够读取其他函数内部变量的函数。只有函数内部的子函数才能读取局部变量,在本质上,闭包是函数内部和函数外部连接起来的桥梁。

    当函数可以记住并访问所在词法作用域时,就产生了闭包,即使函数是在当前词法作用域之外执行。 - - 出自《你不知道的JavaScript(上卷)》

    闭包的定义:

    如果在一个内部函数里,对在外部作用域(但不是全局作用域)的变量进行引用,那么内部函数就被认为是闭包(closure)。

    闭包的特点:

    1. 可以读取自身函数外部的变量(沿着作用域链寻找)先从自身开始查找,如果自身没有才会继续往上级查找,自身如果拥有将直接调用。(哪个离的最近就用哪一个)
    2. 延长内部变量的生命周期
    3. 函数b嵌套在函数a内部
    4. 函数a返回函数b

    闭包的作用:

    在函数a执行完并返回后,闭包使得JavaScript的垃圾回收机制不会收回a所占用的资源,因为a的内部函数b的执行需要依赖a中的变量,闭包需要循序渐进的过程。

    闭包的构成:

    闭包由俩个部分构成:

    • 函数
    • 以及创建该函数的环境

    应用场景:

    1. 保护函数内的变量安全。函数a中只有函数b才能访问,而无法通过其他途径访问到,因此保护了i的安全性。
    2. 在内存中维持一个变量

    了解JAVA的同学肯定知道JAVA是有私有方法的。私有方法只能被一个类中的其他方法所调用,但是JavaScript并没有,所以就需要用闭包来模拟。
    私有方法有利于限制对代码的访问,可以避免非核心的方法干扰代码的公共接口,减少全局污染。

    demo:

    var test = (function() {
    	var a = 1;
    	function add(val){
    		a += val;
    	}
    	return {
    		add1() {
    			add(1);
    		},
    		add2() {
    			add(2);
    		},
    		result() {
    			return a;
    		}
    	}
    })();
    

    上面这种方式也叫做模块模式(module pattern)。
    关于设计模式请看:https://blog.csdn.net/weixin_43606158/article/details/90229052

    拓展:

    回收机制:
    在JavaScript中,如果一个对象不再被引用,那么这个对象就会被GC回收。如果俩个对象互相引用,而不再被第3者所引用,那么这俩个互相引用的对象也会被回收。因为函数a被b引用,b又被a外的c引用,这就是为什么函数a执行后不会被回收的原因。

    简单demo:

    var num = 6;
    function outer() {
    	var num = 1;
    	function inner() {
    		var n = 2;
    		alert(n + num);
    	}
    	return inner
    }
    const test = outer();
    test();
    

    在这里插入图片描述
    结果与我们想的一样,是3。

    闭包的缺点:

    滥用闭包会造成内存泄露,因为闭包中引用到的包裹函数中定义的变量都永远不会被释放,所以我们应该在必要的时候,及时释放这个闭包函数。

    展开全文
  • 理解闭包,原来可以如此简单

    1、概念

    闭包函数:声明在一个函数中的函数,叫做闭包函数。

    闭包:内部函数总是可以访问其所在的外部函数中声明的参数和变量,即使在其外部函数被返回(寿命终结)了之后。

    2、特点

      让外部访问函数内部变量成为可能;

      局部变量会常驻在内存中;

      可以避免使用全局变量,防止全局变量污染;

      会造成内存泄漏(有一块内存空间被长期占用,而不被释放)

    3、闭包的创建:­­­

    闭包就是可以创建一个独立的环境,每个闭包里面的环境都是独立的,互不干扰。闭包会发生内存泄漏,每次外部函数执行的时 候,外部函数的引用地址不同,都会重新创建一个新的地址。但凡是当前活动对象中有被内部子集引用的数据,那么这个时候,这个数据不删除,保留一根指针给内部活动对象。

    闭包内存泄漏为: key = value,key 被删除了 value 常驻内存中; 局部变量闭包升级版(中间引用的变量) => 自由变量;

     

    上面的都是什么鬼,是人话么,能看懂早就看懂了,生气······

    不过,答应我,看完例子再回看上面的概念,会理解的更!透!彻!

    ---------------------------------------------我是容易看懂的分界线-----------------------------------------------

    4、闭包的应用场景

    结论:闭包找到的是同一地址中父级函数中对应变量最终的值

    最终秘诀就这一句话,每个例子请自行带入这个结论!!!!!!!!!!!!!

    /* 例子1 */

    function funA(){
      var a = 10;  // funA的活动对象之中;
      return function(){   //匿名函数的活动对象;
            alert(a);
      }
    }
    var b = funA();
    b();  //10
    

    /* 例子2 */

    function outerFn(){
      var i = 0; 
      function innerFn(){
          i++;
          console.log(i);
      }
      return innerFn;
    }
    var inner = outerFn();  //每次外部函数执行的时候,都会开辟一块内存空间,外部函数的地址不同,都会重新创建一个新的地址
    inner();
    inner();
    inner();
    var inner2 = outerFn();
    inner2();
    inner2();
    inner2();   //1 2 3 1 2 3
    

    /* 例子3 */

    var i = 0;
    function outerFn(){
      function innnerFn(){
           i++;
           console.log(i);
      }
      return innnerFn;
    }
    var inner1 = outerFn();
    var inner2 = outerFn();
    inner1();
    inner2();
    inner1();
    inner2();     //1 2 3 4
    

    /* 例子4 */

    function fn(){
    	var a = 3;
    	return function(){
    		return  ++a;                                     
    	}
    }
    alert(fn()());  //4
    alert(fn()());  //4    
    

    /* 例子5 */

    function outerFn(){
    var i = 0;
      function innnerFn(){
          i++;
          console.log(i);
      }
      return innnerFn;
    }
    var inner1 = outerFn();
    var inner2 = outerFn();
    inner1();
    inner2();
    inner1();
    inner2();    //1 1 2 2
    

    /* 例子6 */

    (function() { 
      var m = 0; 
      function getM() { return m; } 
      function seta(val) { m = val; } 
      window.g = getM; 
      window.f = seta; 
    })(); 
    f(100);
    console.info(g());   //100  闭包找到的是同一地址中父级函数中对应变量最终的值
    

    /* 例子7 */

    function a() { 
      var i = 0; 
      function b() { alert(++i); } 
      return b; 
    } 
    var c = a(); 
    c();      //1 
    c();      //2 
    

    /* 例子8 */

    function f() { 
      var count = 0; 
      return  function() { 
          count++; 
          console.info(count); 
      } 
    } 
    var t1 = f();
    t1();     //1 
    t1();     //2 
    t1();     //3 
    

    /* 例子9 */

    var add = function(x) { 
      var sum = 1; 
      var tmp = function(x) { 
          sum = sum + x; 
          return tmp;    
      } 
      tmp.toString = function() { 
          return sum; 
      }
      return tmp; 
    } 
    alert(add(1)(2)(3));     //6
    

    /* 例子10 */

    var lis = document.getElementsByTagName("li");
    for(var i=0;i<lis.length;i++){
      (function(i){
          lis[i].onclick = function(){
               console.log(i);
          };
      })(i);       //事件处理函数中闭包的写法
    }  
    

    /* 例子11 */

    function m1(){
         var x = 1;
         return function(){
              console.log(++x);
         }
    }
    
    m1()();   //2
    m1()();   //2
    m1()();   //2
    
    var m2 = m1();
    m2();   //2
    m2();   //3
    m2();   //4
    

    /* 例子12 */

    var  fn=(function(){
       var  i=10;
       function  fn(){
          console.log(++i);
       }
       return   fn;
    })() 
    fn();   //11
    fn();   //12
    

    /* 例子13 */

    function love1(){
         var num = 223;
         var me1 = function() {
               console.log(num);
         }
         num++;
         return me1;
    }
    var loveme1 = love1();
    loveme1();   //输出224
    

    /* 例子14 */

    function fun(n,o) {
        console.log(o);
        return {
             fun:function(m) {
                   return fun(m,n);
             }
        };
    }
    var a = fun(0);  //undefined
    a.fun(1);  //0  
    a.fun(2);  //0  
    a.fun(3);  //0  
    var b = fun(0).fun(1).fun(2).fun(3);   //undefined  0  1  2
    var c = fun(0).fun(1);  
    c.fun(2);  
    c.fun(3);  //undefined  0  1  1
    

    /* 例子15 */

    function fn(){
       var arr = [];
       for(var i = 0;i < 5;i ++){
    	 arr[i] = function(){
    		 return i;
    	 }
       }
       return arr;
    }
    var list = fn();
    for(var i = 0,len = list.length;i < len ; i ++){
       console.log(list[i]());
    }  //5 5 5 5 5
    

    /* 例子16 */

    function fn(){
      var arr = [];
      for(var i = 0;i < 5;i ++){
    	arr[i] = (function(i){
    		return function (){
    			return i;
    		};
    	})(i);
      }
      return arr;
    }
    var list = fn();
    for(var i = 0,len = list.length;i < len ; i ++){
      console.log(list[i]());
    }  //0 1 2 3 4
    

     

    展开全文
  • 深入理解JS闭包

    万次阅读 多人点赞 2018-07-23 14:50:17
    关于JS中闭包的理解,相信很多人都和笔者一样刚开始很是困惑。笔者也是在看了很多前辈的文章后,总结出一点自己的理解。记录与此,囿于笔者水平有限 ,若有错误之处,恳请不啬赐教。 你可以在一个函数里面嵌套另外...

    关于JS中闭包的理解,相信很多人都和笔者一样刚开始很是困惑。笔者也是在看了很多前辈的文章后,总结出一点自己的理解。记录与此,囿于笔者水平有限 ,若有错误之处,恳请不啬赐教。

    你可以在一个函数里面嵌套另外一个函数。嵌套(内部)函数对其容器(外部)函数是私有的。它自身也形成了一个闭包。一个闭包是一个可以自己拥有独立的环境与变量的的表达式(通常是函数,因为ES6有了块级作用域的概念)。

    https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide/Functions(上面这句话摘自这个网址)

    第一部分:初遇闭包

    http://www.runoob.com/js/js-function-closures.html

    什么是闭包?闭包有什么作用?这是我遇到闭包时的第一反应。

    闭包在JavaScript高级程序设计(第3版)中是这样描述:闭包是指有权访问另一个函数作用域中的变量的函数。

    那么闭包的作用也就很明显了。

    1. 可以在函数的外部访问到函数内部的局部变量。 
    2. 让这些变量始终保存在内存中,不会随着函数的结束而自动销毁。

    在上面的代码中,闭包指的就是function () {return counter += 1;}这个函数。首先解释一下这段代码,在变量add被赋值之前,第一个function执行了一次(执行且仅会执行一次),因为这是一个函数表达式声明方式并且声明后加上了(),所以会自动执行一次。执行后add被赋值(匿名函数)了,add= function () {return counter += 1;} 。然后每次调用add()函数时,返回的都是这个函数,因为这个函数在第一个函数的内部,所以即使第一个函数执行完了,第二个函数依然能访问counter(JS设计的作用域链,当前作用域能访问上级的作用域)。

    闭包是可以在另一个函数的外部访问到其作用域中的变量的函数。而被访问的变量可以和函数一同存在。即使另一个函数已经运行结束,导致创建变量的环境销毁,也依然会存在,直到访问变量的那个函数被销毁。当然,如果仅仅是做一个简单的计数器,大可不用这样麻烦。下面这简短的代码就能轻松实现。

    var a = 0;
    function myFunction(){
    	a++;
        document.getElementById("demo").innerHTML = a;
    }

    推荐一篇博客:https://blog.csdn.net/qq_36276528/article/details/70049825(写得很有深度)

    第二部分:牛客翻船

    https://www.nowcoder.com/questionTerminal/da4115e308c948169a9a73e50d09a3e7

    下面是这个题目的解答:
    每个li标签的onclick事件执行时,本身onclick绑定的function的作用域中没有变量i,i为undefined,则解析引擎会寻找父级作用域,发现父级作用域中有i,且for循环绑定事件结束后,i已经赋值为4,所以每个li标签的onclick事件执行时,alert的都是父作用域中的i,也就是4。这是作用域的问题。

    闭包只能取得包含函数中任何变量的最后一个值。因为别忘了闭包所保存的是整个变量对象,而不是某个特殊的变量。

    这是在循环体中创建闭包的常见错误。https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Closures(一定要看这篇)

    这里面给onclick赋值的是闭包。很多人会问为什么是闭包?之前闭包不是函数A里的函数B吗?函数B用来访问函数A的变量,称函数B是闭包,题目中只有一个函数为什么也是闭包。其实,用两个函数形成闭包只是一般形式。闭包真正的含义是,如果一个函数访问了此函数的父级及父级以上的作用域变量,就可以称这个函数是一个闭包。

    <script>
        var a = 1;
        (function test (){
    		alert(a);
    	})()
    </script>

    所以上面的function都可以称之为闭包(匿名闭包函数)。

    这里还是作用域的问题,那么我们把每次的i都保存到一个变量中,匿名闭包就可以实现想要的效果。

    var elements=document.getElementsByTagName('li');
        var length=elements.length;
        for(var i=0;i<length;i++){
            elements[i].onclick=function(num){
            return function() {
                    alert(num);
            };
        }(i);
        }

    这样就使用了闭包,这里面的闭包指的是function() {alert(num);};第二个function里面弹出的num是第一个function的参数,通过(i)执行了这里面的第一个函数,同时i的值被保存到num中。每个点击事件中都有一个局部变量num,num保存的是相应的i值。

    第三部分:let的横空出世

    上面的牛客题目只需要将for(var i=0;i<length;i++)中的var改成let就能实现想要的效果,这让在循环体内创建闭包具有更好的可读性。let的简单介绍:https://mp.csdn.net/postedit/81065540

    let的到来,让令人诟病的JS获得了一丝生机,也补上了JS没有块级作用域的短板。ECMAScript6还有很多新特性,笔者也在不断学习中。

    第四部分:闭包的应用

    函数工厂和闭包模拟私有方法

    https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Closures(这篇讲得很好,希望读者们读透)

    展开全文
  • 一:什么是闭包闭包就是能够读取其他函数内部变量的函数,说白了闭包就是个函数,只不过是处于其他函数内部而已。 由于在javascript中,只有函数内部的子函数才能读取局部变量,所以说,闭包可以简单理解成...

    一:什么是闭包?

    闭包就是能够读取其他函数内部变量的函数,说白了闭包就是个函数,只不过是处于其他函数内部而已。

    由于在javascript中,只有函数内部的子函数才能读取局部变量,所以说,闭包可以简单理解成“定义在一个函数内部的函数“。

    所以,在本质上,闭包是将函数内部和函数外部连接起来的桥梁。

    知乎大神说:闭包是指在 JavaScript 中,内部函数总是可以访问其所在的外部函数中声明的参数和变量,即使在其外部函数被返回(寿命终结)了之后。

    二:用途是什么?

    1.访问函数内部的变量

    2.防止函数内部的变量执行完城后,被销毁,使其一直保存在内存中。

    写一个关于闭包的例子:

    function outer(x) {

    // 参数相当于局部的变量

        function inner(y) {

           console.log(x + y);

    }

       return inner;

    }

    var closure = outer(3);

    closure(7); // 输出10

     

    inner函数把自己内部的语句,和自己在声明时所处的作用域一起封装成了一个密闭的环境,我们就称之为闭包。

    函数本身就是一个闭包,函数在定义的时候,就能记住自己的外部环境和内部语句,每次执行的时候,会参考定义时的密闭环境。

    关于闭包的用处的例子:看的MDN网站上的例子,讲的非常清楚了

    var makeCounter = function() {
      var privateCounter = 0;
      function changeBy(val) {
        privateCounter += val;
      }
      return {
        increment: function() {
          changeBy(1);
        },
        decrement: function() {
          changeBy(-1);
        },
        value: function() {
          return privateCounter;
        }
      }  
    };

    var Counter1 = makeCounter();
    var Counter2 = makeCounter();
    console.log(Counter1.value()); /* logs 0 */
    Counter1.increment();
    Counter1.increment();
    console.log(Counter1.value()); /* logs 2 */
    Counter1.decrement();
    console.log(Counter1.value()); /* logs 1 */
    console.log(Counter2.value()); /* logs 0 */

    每次调用其中一个计数器时,通过改变这个变量的值,会改变这个闭包的词法环境。然而在一个闭包内对变量的修改,不会影响到另外一个闭包中的变量。以这种方式使用闭包,提供了许多与面向对象编程相关的好处 —— 特别是数据隐藏和封装

    缺点:

    如果不是某些特定任务需要使用闭包,在其它函数中创建函数是不明智的,因为闭包在处理速度和内存消耗方面对脚本性能具有负面影响。

    实际项目应用:

    封装一个公共弹框,点击确定取消按钮,会触发退订事件,调用退订接口,成功之后还会刷新列表。

    弹框组件接受一个 确定按钮的事件,OK参数。

    如果 OK 不写成箭头函数,那么里面的this 指向的是OK 而不是vue ,就无法执行,methods 的方法,也可以 在外部

    let _this = this;

    ok: function() {

    _this.exitOrder();

    }

    这么写也可以。

     

    展开全文
  • 彻底理解js中的闭包

    万次阅读 多人点赞 2017-07-29 20:42:56
    闭包是js的一个难点也是它的一个特色,是我们必须掌握的js高级特性,那么什么是闭包呢?它又有什么用呢? 我们都知道,js的作用域分两种,全局和局部,基于我们所熟悉的作用域链相关知识,我们知道在js作用域环境中...
  • 闭包

    2020-11-16 22:05:30
    这时候我们需要闭包,首先我们需要知道闭包是什么?   闭包是指有权访问另一个函数作用域中的变量的函数,创建闭包的最常见的方式就是在一个函数内创建另一个函数,通过另一个函数访问这个函数的局部变量。   ...
  • JS高级(8)—— 闭包

    2020-11-22 09:34:54
    闭包指有权访问另一个函数作用域中变量的函数。—>闭包是函数 简单理解就是:一个作用域可以访问另外一个函数内部的局部变量。 三、产生闭包的条件 当一个嵌套的内部(子)函数引用了嵌套的外部(父)函数的变量...
  • 闭包

    2020-11-10 17:05:46
    闭包 一、什么是闭包? 特点: 1、函数嵌套函数 2、内部函数可以引用外部函数的参数和变量 3、参数和变量不会被垃圾回收机制所收回 二、闭包有什么好处,应用在哪里? 好处: 1、希望一个变量常驻在内存当中 2、避免全局...
  • 闭包

    2019-10-12 19:45:37
    一、什么是闭包? 找一个作用域中可以访问另一个作用域的变量 理解闭包的关键在于:外部函数调用之后其变量对象本应该被销毁,但闭包的存在使我们仍然可以访问外部函数的变量对象,这就是闭包的重要概念。 二、...
  • 为什么js会有闭包

    千次阅读 2018-07-23 12:18:02
    我一愣,说我理解的是,js的闭包其实是对js函数作用域特性的一种利用,因为函数内定义的局部变量不能被外部直接获取,而函数却可以访问到其外部作用域的变量。所以我们可以在函数内部定义一个访问局部变量的方法并将...
  • 在很多情况下我们会遇到闭包这个问题,也有很多人不太理解闭包以及闭包的形成,下面就给大家简单说下闭包。首先说什么是闭包闭包就是 有权访问另一个函数作用域变量的函数都是闭包,让我们举个例子在我们写代码的...
  • 闭包

    2016-03-05 11:26:16
    闭包  编辑 闭包是指可以包含自由(未绑定到特定对象)变量的代码块;这些变量不是在这个代码块内或者任何全局上下文中定义的,而是在定义代码块的环境中定义(局部变量)。“闭包” 一词来源于以下两者的...
  • 闭包特点 1.函数嵌套函数 2. 函数内部可以引用外部的参数和变量 3. 参数和变量不会被垃圾回收机制回收,而是在保存在内存中 闭包的好处 1.希望变量存在缓存中 2.避免全局污染 闭包的两种方式 1.函数作为返回值 ...
  • 闭包

    2019-08-13 10:18:23
    闭包 能够读取其他函数内部变量的函数(内层作用域可以访问外层作用域的变量) 闭包的产生:产生于多个函数的嵌套之间 实际开发中闭包的应用:封装变量,收敛权限 闭包的缺点:滥用闭包可能造成内存泄漏。...
  • 闭包

    2016-02-21 21:01:54
    //声明一个闭包 function f1() { var week="Sunday"; function f2() { console.log('星期:'+week); } return f2; } var ff=f1(); //以上代码已经形成一个闭包
  • 闭包

    2019-07-30 19:01:04
    文章目录闭包 闭包 什么是闭包 闭是封闭(函数中的函数),包是包含(该内部函数对外部函数作用域而非全局作用域变量的引用) 闭包: 内部函数对外部函数作用域里的变量的引用 函数内的属性,都是有生命周期,都...
  • 闭包

    2016-09-22 09:00:41
    1.闭包的含义: 闭包就是能够读取其他函数内部变量的函数。 (1).闭包外层是一个函数。 (2).闭包内部都有函数。 (3).闭包会return内部函数。 (4).闭包返回的函数内部不能有return(因为这样就真的结束了)。 (5...
  • 闭包

    2017-09-25 14:48:38
    在Web开发中,在使用JavScript时,就算没用过,也听说过闭包这个名词。闭将外部作用域中的局部变量封闭起来的函数成为闭包,本质就是一个函数。 闭包的作用 - 保护函数内变量的安全,不能被外部随意修改,只能通过...
  • 闭包

    2018-01-22 14:56:54
    从技术讲,所有的javascript函数都闭包,他们都是对象,它们都关联到作用域链,定义大多数函数时的作用域链在调用函数时依然有效,但这并不影响闭包,当调用后函数是闭包所指向的作用域链和定义函数时的作用域链不是同一个...
  • 闭包

    2018-06-03 00:30:09
    闭包是指有权访问另一个函数作用域变量的函数。创建闭包的方式:在一个函数的内部创建另一个函数,这个函数有权访问包含函数的活动对象即全局对象。function closure(){ //执行clsure创建一个包含arguments和person...

空空如也

1 2 3 4 5 ... 20
收藏数 164,796
精华内容 65,918
关键字:

闭包