• JavaScript闭包


    闭包是JavaScript中的一个难点,同时也是它的特色,JavaScript的很多高级应用都要依靠闭包来实现。以下是我学习闭包的记录,希望对你有些帮助。

    变量作用域

    在学习闭包之前,我们首先要理解JavaScript不同与其他语言独特的变量作用域。在JavaScript中,不存在局部作用域的概念,但是有全局作用域以及函数作用域。全局作用域与其他语言的相同,没有需要注意的地方,而函数作用域是指函数内部声明的变量在函数外部无法直接访问。

    var a = 99;
    function f1() {
        console.log(a);
    }
    f1();
    

    上面的代码中,f1可以读取到全局变量a,而下面的代码中a无法被访问。

    function f1() {
        var a = 99;
    }
    console.log(a);
    

    如何从外部读取函数内部声明的变量?

    在某些情况下,我们可能需要得到函数内部的变量,正常情况下是无法做到的,因此需要用特殊的办法。

    function f1() {
        var a = 99;
        function f2() {
            console.log(a);
        }
    }
    

    上面代码中,我们在函数f1中定义另一个函数f2,这样f1中的所有变量对于f2来说就是可见的,既然f2可以读取到f1中的变量,那么我们只要把f2作为f1的返回值,我们就可以在f1的外部读取到它内部的变量了。

    function f1() {
        var a = 99;
        function f2() {
            console.log(a);
        }
        return f2;
    }
    var result = f1();
    result();
    

    此时,就形成了一个简单的闭包。因此,闭包就可以简单的理解为函数中的函数,而本质上,闭包就是一个连接函数内部和外部的桥梁。

    闭包的特性

    闭包会使得函数中的变量都被保存到内存中。首先我们先看一下以下两个例子

    function A() {
        var count = 0;
        function B() {
           count++;
           console.log(count);
        }
        return B;
    }
    var C = A();
    C(); // 1
    C(); // 2
    C(); // 3
    

    count是函数A中的一个变量,它的值在函数B中被改变,函数B每执行一次,count的值就在原来的基础上累加1,因此,函数A中的count变量会一直保存在内存中。

    function A(x) {
        function B(y) {
            console.log(x+y);
        }
    return B;
    }
    var C = A(3);
    C(5); //8
    

    当3传入A函数后,B函数就会记住这个值,所以在后面传入5的时候只会对B函数中的y赋值,所以最后会输出8。

    使用闭包的注意点

    由于上述闭包的特性,每次使用闭包都会大量增加内存的消耗,所以不能滥用闭包,否则会影响网页的性能。我们也可以在函数退出前,使函数内变量指向null来手动删除变量。我们可以来看下一道经典的面试题来理解。

    function outer(){
        var num = 0; //内部变量
        return function add() { //通过return返回add函数,就可以在outer函数外访问了
            num++; //内部函数有引用,作为add函数的一部分了
            console.log(num);
        };
    }
    var func1 = outer();
    func1(); //实际上是调用add函数, 输出1
    func1(); //输出2 因为outer函数内部的私有作用域会一直被占用
    var func2 = outer();
    func2(); // 输出1  每次重新引用函数的时候,闭包是全新的。
    func2(); // 输出2  
    

    参考文章

  • 相关阅读:
    在Spring中使用cache(EhCache的对象缓存和页面缓存)
    halcon 模板匹配 -- 转化 vector_angle_to_rigid
    halcon 模板匹配 -- find_shape_model
    halcon 模板匹配 -- create_shape_model
    C#快速获取指定网页源码的几种方式,并通过字符串截取函数 或 正则 取指定内容(IP)
    C# Socket通讯 本机多网卡,指定网卡通讯
    C# 获取所有网卡信息
    C#关闭退出线程的几种方法
    C#多线程方法 可传参
    C# Datetime 使用详解
  • 原文地址:https://www.cnblogs.com/xueyubao/p/11701404.html
Copyright © 2020-2023  润新知