zoukankan      html  css  js  c++  java
  • js 闭包(新)

    前言

    旧的没有搬过来,先写一下新的感悟。

    正文

    ECMAScript中,闭包指的是:
    
    从理论角度:所有的函数。因为它们都在创建的时候就将上层上下文的数据保存起来了。哪怕是简单的全局变量也是如此,因为函数中访问全局变量就相当于是在访问自由变量,这个时候使用最外层的作用域。
    从实践角度:以下函数才算是闭包:
          1.即使创建它的上下文已经销毁,它仍然存在(比如,内部函数从父函数中返回)
          2.在代码中引用了自由变量
    

    什么是自由变量:

    自由变量是指在函数中使用的,但既不是函数参数也不是函数的局部变量的变量。
    

    那么我们现在只考虑实践角度,第二点很好满足,第一点有一丢丢难呢。

    先看下闭包:

    function checkscope(){
        var scope = "local scope";
        function f(){
            return scope;
        }
        return f;
    }
    
    var foo = checkscope();
    foo();
    

    按照我的上一篇js的上下文。

    理论上scope 是访问不到var scope = "local scope";的。

    我在这里简单的分析一下,详细可以去看我的。

    首先得到全局上下文,进入栈中。

    然后checkscope 上下文进入栈。

    当执行完毕,checkscope 上下文出栈了。

    问题就在这里,既然上下文出栈了,那么应该f这个函数执行的时候,就应该访问不到checkscope 的上下文了,垃圾就会回收checkscope 的上下文。

    这个问题就出现了。

    但是你没有有听说过闭包造成内存问题?

    问题就出再f创建的时候,会扫码他所在环境的上下文,如果引用了上下文的作用链对象,那么会保留上下文。

    function a()
    {
    	var x=1;
    	var c= function b()
    	{
    	   return function (){
    		   return x;
    	   }
    	}
    	return function()
    	{
    		return c;
    	}
    }
    

    console.log(a()()()());
    只要是作用链上的都会保留到,返回结果为1。

    var data = [];
    
    for (var i = 0; i < 3; i++) {
      data[i] = function () {
        console.log(i);
      };
    }
    
    data[0]();
    data[1]();
    data[2]();
    

    为何其会返回都是3?
    按照上下文理解,那么是:

    在执行匿名函数的时候,上下文栈中只剩下全局上下文,访问的就只有去全局的。
    

    那么可以这样写:

    var data = [];
    
    for (var i = 0; i < 3; i++) {
      data[i] = (function (i) {
            return function(){
                console.log(i);
            }
      })(i);
    }
    
    data[0]();
    data[1]();
    data[2]();
    

    关键部分在这个i:

     (function (i) {
            return function(){
                console.log(i);
            }
      })(i);
    

    这样i,相当于这样的。

     (function (i) {
            var i=i;
            return function(){
                console.log(i);
            }
      })(i);
    

    这就是说这个i和循环中的i没有半毛钱关系,因为其不是引用对象。

    下面我写了一个引用对象的:

    var data=[];
    var args={i:0};
    for (var i = 0; i < 3; i++) {
    	args.i=i;
    	data[i] = (function (args) {
    		return function () {
    			console.log(args.i);
    		}
    	})(args);
    }
    data[0]();
    data[1]();
    data[2]();
    

    这样的闭包不仅没有效果,而且还出内存问题。

  • 相关阅读:
    经典javascript
    大话prototype
    DataTable使用方法总结
    实验四 Web服务器1socket编程
    2.4 OpenEuler中C语言中的函数调用测试
    20191323王予涵第13章学习笔记
    20191323王予涵第十三章学习笔记
    2.5 OpenEuler 中C与汇编的混合编程
    个人贡献
    20191323王予涵第十二章学习笔记
  • 原文地址:https://www.cnblogs.com/aoximin/p/12761435.html
Copyright © 2011-2022 走看看