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

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

    闭包的简介:

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

    当函数可以记住并访问所在词法作用域时,就产生了闭包,即使函数是在当前词法作用域之外执行。 - - 出自《你不知道的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-26 10:45:49
    关于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();

    }

    这么写也可以。

     

    展开全文
  • 理解JavaScript中的闭包

    千人学习 2019-06-27 10:46:04
    本课程介绍什么是闭包闭包有哪些使用场景,常见的使用错误。
  • 闭包

    千次阅读 2018-08-19 10:17:46
    那么闭包的定义到底是什么了。大家一定要注意,不是说能够访问到其他作用域的变量就是闭包,这是很笼统的。准确来说,闭包是基于正常的垃圾回收处理机制下的。也就是说,一般情况一个函数(函数作用域)执行完毕,...
  • 为什么js会有闭包

    千次阅读 2018-07-23 14:37:33
    我一愣,说我理解的是,js的闭包其实是对js函数作用域特性的一种利用,因为函数内定义的局部变量不能被外部直接获取,而函数却可以访问到其外部作用域的变量。所以我们可以在函数内部定义一个访问局部变量的方法并将...
  • 彻底理解js中的闭包

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

    万次阅读 多人点赞 2020-03-27 10:49:37
    在理解闭包以前.最好能先理解一下作用域链的含义,简单来说,作用域链就是函数在定义的时候创建的,用于寻找使用到的变量的值的一个索引,而他内部的规则是,把函数自身的本地变量放在最前面,把自身的父级函数中的变量...
  • 闭包:外部函数定义的内部函数就是闭包闭包的作用及好处:闭包给访问外部函数定义的内部变量创造了条件。也将关于函数的一切封闭到了函数内部,减少了全局变量,这也是闭包的真实含义。 与普通函数的区别: 1,...
  • 什么是闭包?它的优点与缺点是?

    千次阅读 2017-11-11 17:52:50
    闭包:能够读取其他函数内部变量的函数。(应用场景:要获取某函数内部的局部变量) 闭包的优点:1.能够读取函数内部的变量 2.让这些变量一直存在于内存中,不会在调用结束后,被垃圾回收机制回收 闭包的缺点:正...
  • python中的闭包

    万次阅读 多人点赞 2019-02-12 21:07:59
    Python中的闭包是一个比较模糊的概念,有很多朋友都认为不好理解,但是随着深入学习,就会发现闭包无论如何都是需要去理解的,下面我将自己对闭包的理解进行阐述,希望能够对你有所帮助 ~ 闭包的理解 我们可以将闭包...
  • 一个超简单的闭包示例

    千次阅读 2017-12-25 14:20:58
    一个超简单的闭包示例
  • Scala 中闭包的概念

    万次阅读 2015-05-07 17:17:08
    闭包的实质就是代码与用到的非局部变量的混合,即: 闭包 = 代码 + 用到的非局部变量 例如,我们定义一个值函数 sum: 此时 Scala 解释器提示找不到 y 这个值,这是因为我们根本就没有定义 y 这个变量,...
  • 在很多情况下我们会遇到闭包这个问题,也有很多人不太理解闭包以及闭包的形成,下面就给大家简单说下闭包。首先说什么是闭包闭包就是 有权访问另一个函数作用域变量的函数都是闭包,让我们举个例子在我们写代码的...
  • 【数据库】—闭包

    万次阅读 多人点赞 2016-09-23 09:58:09
    前言: 由于函数依赖是用命题形式定义的,因此函数依赖黄子健存在着逻辑蕴涵的关系。比如A决定 B(也可以用由A指向B的箭头表示)和B决定C在关系模式R中成立,...这个问题就是FD之间的逻辑蕴涵问题,我们把它称为闭包
  • JS中闭包的特性及其优缺点

    千次阅读 2017-12-26 16:20:21
    function Student(){ var age=22; function addAge(){ age++; alert(age); } return addAge; } var fn=Student();...//弹出23闭包有三个特性: 函数嵌套函数。 函数内部可以引用外部的参数和变量。
  • 传递闭包的通俗理解

    千次阅读 多人点赞 2019-03-18 16:25:01
    而传递闭包显示的是传递关系,如a不能直接到c,却可以通过a到b到d再到c,因此a到c为1。 另外矩阵A进行自乘即得到的矩阵中,为1的值表示走最多两步可以到达。矩阵中为1的值表示,最多走三步可以到达。 ...
  • JS之经典for循环闭包问题解决方法

    万次阅读 2015-01-30 13:14:47
    JS之经典for循环闭包问题解决方法 像这样一个代码片段,初学者会理所当然地认为依次点击Li会弹出相应的0、1、2、3、4、5,但实际结果却是这样的 我们无论点哪个按钮,最后弹出来的都是6。经典的for循环闭包问题...
  • Python基础之闭包函数

    千次阅读 2019-03-13 01:12:30
    文章目录闭包的概念闭包实例如何判断是否是闭包函数 闭包的概念 在 Python 中很多地方都会使用到闭包,那么究竟什么叫做闭包呢? 在维基百科上是这么解释的。 在一些语言中,在函数中可以(嵌套)定义另一个...
1 2 3 4 5 ... 20
收藏数 151,835
精华内容 60,734
关键字:

闭包