zoukankan      html  css  js  c++  java
  • 闭包和匿名函数

    在高级程序设计里,描述闭包是指有权访问另一个函数作用域中的变量的函数。

    而经常创建方式是一个函数里包含另一函数。

    而匿名函数就如“匿名”这两个意思一样。

    所以匿名函数和闭包不是同一个概念。

    在高级程序设计里描述匿名函数的执行环境具有全局性,所以this指向为window。这就是

    为什么有时候发现this指向,不是自己所想的对象的问题。

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Document</title>
    </head>
    <body>
        <script>
            var name="a";
            var obj={
                name:"b",
                showFn:function(){
                    return (function(){
                        return this.name;
                    })();
                }
            }
            console.log(obj.showFn());
        </script>
    </body>
    </html>
    
    打印结果为“a”

    测试中可知:this指向window,所以才打印出“a”;

    闭包:

    简单的例子:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Document</title>
    </head>
    <body>
        <script>
         name="cde"; function a(){ var name="abc"; function b(){ alert(name); }; b(); } a(); </script> </body> </html>

    然而使用画图更好理解:

     而这里的0表示自己的执行环境,1是上级执行环境,2是上上级执行环境,以此类推。

    而变量查找是就近原则的,在自己最近的作用域查找到就会停止查找。

    而这里活动对象的理解,很重要,因为只有函数在被调用时才是变量对象才是活动的,

    才会去查找所要的变量。

    如:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Document</title>
    </head>
    <body>
        <script>
            function a(){
                var name="abc";
                var arr=[];
                for(var i=0;i<4;i++){
                    arr[i]=function b(){
                        alert(i);
                    };
                }
                return arr;
                
            }
            a()[0]();
            a()[1]();
            a()[2]();
        </script>
    </body>
    </html>

    弹出的结果都是4;

    这是因为函数执行时内部函数没有在执行,而是内部函数执行完之后被调用时才执行,所以

    这时活动对象上级作用域的变量都是同一一个值了;

    还有闭包的执行环境结束了,活动对象也不会被销毁,这就像全局作用域,所以闭包里的变量是不会被

    回收的,会一直保存着。

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Document</title>
    </head>
    <body>
        <script>
            function a(){
                var num=0;
                return function b(){
                    num++;
                    console.log(num);
                }
            }
            var m1=a();
            m1();
            m1();
            m1();
        </script>
    </body>
    </html>
    结果:
    1,,2,3

    虽然使用闭包要谨慎;

    但使用闭包可以避免全局污染的问题。

    新扩充理解:

    闭包:有权访问另外函数的作用域中的变量的函数

    1、函数嵌套函数
    2、内部函数可以引用外部函数的参数和变量

    闭包内的变量是不会被垃圾回收机制回收

    好处:
    1、希望一个变量长期驻扎在内存当中
    2、避免全局变量的污染
    3、私有成员


    用法:
    模块化代码


    内存泄漏就是关闭当前页面,变量还是占据内存,不释放,只有当浏览器关闭时才释放。这样很消耗cpu

    测试代码:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Document</title>
    </head>
    <body>
    <ul>
        <li>abc1</li>
        <li>abc2</li>
        <li>abc3</li>
        <li>abc4</li>
        <li>abc5</li>
    </ul>
    <div id="text"></div>
        <script>
            var aLi=document.querySelectorAll("ul li");
            var t=document.querySelector("#text");
            for(var i=0;i<aLi.length;i++){
                // 这里的i值都是5
                // aLi[i].onclick=function(){
                //     t.innerHTML=i;
                // }
                /*使用闭包的特性解决这个问题
                    闭包的变量不会被释放,闭包可以访问外部函数的参数和变量
                */
                //(function a(){})括号括起来的是函数表达式
                //因为(function(){})()循环去执行这个,其实是循环创建函数
                //所以循环多少次就创建了多少个函数,就有多少个闭包
                // aLi[i].onclick=(function(i){
                //     return function(){
                //         t.innerHTML=i;
                //     }
                // })(i)
                //这也是一种方式,但也是使用了闭包的特性
                (function(i){
                    aLi[i].onclick=function(){
                        t.innerHTML=i;
                    }
                })(i)
            }
        </script>
    </body>
    </html>
  • 相关阅读:
    Windows系统安装mysql5.7*时mysql服务启动失败的解决方法
    安装MySQL出现 This application requires Visual Studio 2013 x64 Redistributable.Please install the Redistributable then run this installer again
    Fiddler抓包流程
    C#使用NPOI根据模板生成Word文件功能实现
    .NET nhibernate 添加新的表运行报is not mapped的问题
    二进制原码、反码、补码和位运算
    【英语】面试常用语整理
    【检测分割算法整理】
    【Leetcode方法比较】DP/滑窗/前缀和
    【Leetcode】数学系列
  • 原文地址:https://www.cnblogs.com/zhangzhicheng/p/6036878.html
Copyright © 2011-2022 走看看