zoukankan      html  css  js  c++  java
  • 浅谈闭包

    一、闭包

    什么是闭包?

    闭包:"利用作用域的嵌套,将原本的局部变量,进化成自由(私有)变量的环境"
    
    闭包的原理:
        局部作用域,局部变量的生命周期,朝生暮死
        利用作用域的嵌套,触发计算机的垃圾回收机制,将原本要删除的变量,暂时保存起来,可以继续使用
    
    垃圾回收机制:将要删除的数据,先暂时存放在一个临时空间内,不立即删除,如果需要再次使用,可以直接找到该数据,继续使用,直到真正不用了,再被删除

    闭包的应用场景

    • 1、(for)循环中的异步
      for循环之中的i变量会因为for的循环次数被覆盖,所以在for循环内部存在函数时,而且这个函数内会调用i变量,这种情况下就需要用到闭包。
        for(var i=0;i<10;i++){
            console.log(i);        //可以访问到每次的i
        }
    
       " 必须满足两个条件:
            1.在for循环内存在函数
            2.函数内会调用这个变量"
            
        var ali = document.getElementsByTagName("li");
        for(var i=0;i<10;i++){
            ali[i].onclick = function(){
                console.log(i);        //在函数内部就无法访问到外部变量
            }
        }
        如何形成闭包
        var ali = document.querySelectorAll("li");
    // 用法一: 用法一和用法二都是通过匿名函数形成作用域
        for(var i=0;i<ali.length;i++){
            (function(index){
                ali[index].onclick = function(){
                    console.log(index);
                }
            })(i)
        }
    // 用法二:
        for(var i=0;i<ali.length;i++){
            ali[i].onclick = (function(index){
                return function(){
                    console.log(index);
                }
            })(i);
        }
    // 用法三:借助 let/cont 触发之后形成块级作用域,形成闭包,把i的值传到内部的作用域中
        for(let i=0;i<ali.length;i++){
            ali[i].onclick = function(){
                console.log(i);
            }
        }
        
        利用匿名函数将i保存起来了
        "一旦内部函数调用外部函数的局部变量,那么这个时候,这个局部变量就会变成内部函数的私有变量"
    
    • 2、计时器(setTimeout)的回调函数的传参时(还有事件委托的封装也是闭包--day14):
        setTimeout(function (a){
            console.log(a);     //两秒后,undefined       函数被放到setTimeout内部里,内部只有执行,没有传参进去
        }, 2000);
        或
        setTimeout(fn("hello"), 5000);
        function fn(str{
            console.log(str);     //没有延迟,立即打印hello      任何情况下函数名+()都是立即执行
        }
        
        使用闭包: 
        function fn(a){
            return function(){
                console.log(a);     // 三秒后,打印10
            }
        } 
        // function(){console.log(a);}     //  作为fn内部的一个小函数,是一个独立的作用域,可以拿到外面的fn(str)的参数str,将其临时保存起来,等setTimeout到时间了就执行这个小函数
        var f = fn(10);  // fn做参数,把10传入a中
        setTimeout(f, 3000);
    

    闭包的特点

    优点:可以将要删除的数据,保存起来,继续使用,方便 
    可以在函数外部操作内部的数据
    
    缺点:因为要删除的数据,没有被删除,继续存起来,那么占内存,耗性能
         在外部有可能改变内部的数据
    
    "闭包就是将作用域内部和外部连接起来的桥梁"

    闭包番外篇--作用域

    闭包
        var a = 10;
        function fn(){
            var a = 20;
            return function(){
                console.log(a++);
            }
        }
        var f = fn();
        f();
    
    "函数:定义上下文,执行上下文(this)"
    "函数执行时,在函数的内部可以拿到自身的定义作用域中的变量"
    
    作用域链----查资料,理解写法原理

    代码是在运行状态下被执行的,运行在内存中(内存:运行结束后立即删除,硬盘里的东西不会删)


    二、趣味性方法:eval

    eval();
    参数:(只能是)字符
    功能:将字符解析成js代码
    
    var str = "1+1";
        console.log(str);  // 1+1
        console.log(eval(str));  // 2
    var str = "hello";
        console.log(eval(str));  // 报错,把str解析成js代码就报错
    var str = "console.log(123)";
    var str = '[{"name":"admin"},]';
    var str = '[{name:"admin"}]';
    var str = '{"name":"admin"}';
    
    console.log(str);
    
    console.log(eval(str));
    
    console.log(JSON.parse(str));

    三、继承

    1.继承的介绍

    继承:子承父业;一个原本没有某些方法或属性的对象,统一写方法,拿到了另外一个对象的属性和方法
    改变this指向继承(构造函数继承):继承构造函数中的属性和方法
    优点:简单方便易操作,可以多继承
    缺点:只能继承构造函数,不能继承原型
    
    构造函数创建对象
    
    function Fn(){
        this.name = "admin";
    }
    Fn.prototype.init = function(){
        console.log(this.name)
    }
    
    var f1 = new Fn();
    var f2 = new Fn();
    
    console.log(f1);
    console.log(f2);
    console.log(f1 == f2);  // false;
    
    bind()
    call()
    apply()
    
    var obj = {
        name:"admin",
        show:function(){
            console.log(this.name)
        }
    }
    
    var obj2 = {
        name:"root"
    }
    
    obj.show();  // admin
    // obj2.show();
    obj.show.bind(obj2)();  // root
    obj.show.call(obj2);    // root
    obj.show.apply(obj2);   // root

    2.改变this指向继承/构造函数继承

    原型对象继承:继承原型
    优点:简单,方便,可以继承原型身上的方式和属性
    缺单:只能继承原型,不方便传参

    3.原型对象继承

    原型对象继承:继承原型
    优点:简单,方便,可以继承原型身上的方式和属性
    缺单:只能继承原型,不方便传参
  • 相关阅读:
    服务端测试之接口测试工具——postman
    服务端测试之接口测试初探
    项目()已配置为使用IIS Web服务器,但此计算机上...
    其他信息: 在分析完成之前就遇到流结尾。
    WPF 打开指定文件路径的文件资源管理器
    Power BI 可视化交互/视觉对象交互
    ASP.NET 前端Ajax获取数据并刷新
    异常详细信息: System.ArgumentException: 不支持关键字: “metadata”。
    设计模式→单例模式
    <转>记dynamic的一个小坑 -- RuntimeBinderException:“object”未包含“xxx”的定义
  • 原文地址:https://www.cnblogs.com/wufenfen/p/11546649.html
Copyright © 2011-2022 走看看