zoukankan      html  css  js  c++  java
  • JavaScript 闭包

    JavaScript 闭包

    一、变量

    1、JavaScript 变量可以是局部变量或全局变量。

    2、函数可以访问是有函数内部定义的变量,函数也可以访问函数外部定义的变量。

    3、在web页面中全局变量属于 window 对象。

    4、全局变量可应用于页面上的所有脚本。

    5、局部变量只能用于定义它函数内部。对于其他的函数或脚本代码是不可用的。

    6、全局和局部变量即便名称相同,它们也是两个不同的变量。修改其中一个,不会影响另一个的值。

    注意:变量声明是如果不使用 var 关键字,那么它就是一个全局变量,即便它在函数内定义。函数内部声明变量的时候,一定要使用var命令。

    二、变量生命周期

    1、全局变量的作用域是全局性的,即在整个JavaScript程序中,全局变量处处都在。

    2、在函数内部声明的变量,只在函数内部起作用。这些变量是局部变量,作用域是局部性的;函数的参数也是局部性的,只在函数内部起作用。

    三、JavaScript 内嵌函数

    1、所有函数都能访问全局变量。  

    2、在 JavaScript 中,所有函数都能访问它们上一层的作用域。

    3、JavaScript 支持嵌套函数。嵌套函数可以访问上一层的函数变量。

    4、内部函数也可以像其他函数一样引用全局变量。

    5、只要存在调用内部函数的可能,JavaScript就需要保留被引用的函数。而且JavaScript运行时需要跟踪引用这个内部函数的所有变量,直到最后一个变量废弃,JavaScript的垃圾收集器才能释放相应的内存空间。

    四、JavaScript 闭包

    闭包是指有权限访问另一个函数作用域的变量的函数。

    由于在Javascript语言中,只有函数内部的子函数才能读取局部变量,因此可以把闭包简单理解成"定义在一个函数内部的函数"。所以,在本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁。

    1.1实例

    var add = (function () {
        var counter = 0;
        return function () {return counter += 1;}
    })();

    add();
    add();
    add();

    // 计数器为 3

    1.2实例解析

    变量 add 指定了函数自我调用的返回字值。

    自我调用函数只执行一次。设置计数器为 0。并返回函数表达式。

    add变量可以作为一个函数使用。非常棒的部分是它可以访问函数上一层作用域的计数器。

    这个叫作 JavaScript 闭包。它使得函数拥有私有变量变成可能。

    计数器受匿名函数的作用域保护,只能通过 add 方法修改。

    注意: 闭包是可访问上一层函数作用域里变量的函数,即便上一层函数已经关闭。

    2.1实例(一个经典错误)

    页面上有若干个div, 我们想给它们绑定一个onclick方法,于是有了下面的代码:

    <div id="divTest">

            <span>0</span> <span>1</span> <span>2</span> <span>3</span>

        </div>

        <div id="divTest2">

            <span>0</span> <span>1</span> <span>2</span> <span>3</span>

    </div>

    $(document).ready(function() {

                var spans = $("#divTest span");

                for (var i = 0; i < spans.length; i++) {

                    spans[i].onclick = function() {

                        alert(i);

                    }

                }

            });

    很简单的功能可是却偏偏出错了,每次alert出的值都是4,简单的修改就好使了 

    var spans2 = $("#divTest2 span");

            $(document).ready(function() {

                for (var i = 0; i < spans2.length; i++) {

                    (function(num) {

                        spans2[i].onclick = function() {

                            alert(num);

                        }

                    })(i);

                }

            });

    2.2实例解析

    for (var i = 0; i < spans.length; i++) {           spans[i].onclick = function() {               alert(i);           }       }

     

    上面代码在页面加载后就会执行,当i的值为4的时候,判断条件不成立,for循环执行完毕,但是因为每个span的onclick方法这时候为内部函数,所以i被闭包引用,内存不能被销毁,i的值会一直保持4,直到程序改变它或者所有的onclick函数销毁(主动把函数赋为null或者页面卸载)时才会被回收。这样每次我们点击span的时候,onclick函数会查找i的值(作用域链是引用方式),一查等于4,然后就alert给我们了。而第二种方式是使用了一个立即执行的函数又创建了一层闭包,函数声明放在括号内就变成了表达式,后面再加上括号括号就是调用了,这时候把i当参数传入,函数立即执行,num保存每次i的值。

    使用闭包的注意点:

    1)由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。

    2)闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。

  • 相关阅读:
    Spring AOP概念理解
    五分钟快速掌握RPC原理及实现
    Linux常用命令汇总
    一致性哈希算法原理
    RPC原理及实现
    IO设计模式:Reactor和Proactor对比
    到底什么时候该使用MQ?
    eclipse查看一个方法被谁引用(调用)的快捷键四种方式
    maven build pulgin
    VSCode 常用setiings.json设置
  • 原文地址:https://www.cnblogs.com/luodan/p/4588351.html
Copyright © 2011-2022 走看看