zoukankan      html  css  js  c++  java
  • 5.Javascript闭包得实现原理和作用

    闭包的实现原理和作用

    1、闭包的概念:指有权访问另一个函数作用域中的变量的函数,一般情况就是在一个函数中包含另一个函数。

    2、闭包的作用:访问函数内部变量、保持函数在环境中一直存在,不会被垃圾回收机制处理

          因为函数内部声明 的变量是局部的,只能在函数内部访问到,但是函数外部的变量是对函数内部可见的,这就是作用域链的特点了。

     子级可以向父级查找变量,逐级查找,找到为止

     1 function  bar(){
     2         //外层函数声明的变量
     3         var value=1;
     4 
     5         function foo(){
     6             console.log(value);
     7         }
     8         return foo();
     9     };
    10     var bar2=bar;
    11     //实际上bar()函数并没有因为执行完就被垃圾回收机制处理掉
    12     //这就是闭包的作用,调用bar()函数,就会执行里面的foo函数,foo这时就会访问到外层的变量
    13     bar2();

    因此我们可以在函数内部再创建一个函数,这样对内部的函数来说,外层函数的变量都是可见的,然后我们就可以访问到他的变量了。

    3、闭包的优点:

    • 方便调用上下文中声明的局部变量
    • 逻辑紧密,可以在一个函数中再创建个函数,避免了传参的问题

    4、闭包的缺点:

          因为使用闭包,可以使函数在执行完后不被销毁,保留在内存中,如果大量使用闭包就会造成内存泄露,内存消耗很大

    实际开发中JS闭包的应用

    1。在函数外使用函数内的变量 .函数作为返回值   (闭包作用:避免变量被环境污染)

    1 function F1(){
    2   var a = 100;
    3     return function(){
    4       console.log(a)    
    5     }
    6 }
    7 var f1 =F1();
    8 var a = 200;
    9 f1()//100

    1 function init(){
    2     var name = "hello world";//name是一个被init创建的局部变量
    3     function sayName(){//sayName是一个内部函数,闭包
    4         alert(name);//使用了父级函数声明的变量name
    5     }
    6     sayName();
    7 }
    8 init();//"hello world"

    2.函数作为参数传递

     1 function F1(){
     2    var a = 100;
     3     return function(){
     4       console.log(a)    
     5     }
     6 }
     7 var f1 =F1();
     8 function F2(fn){
     9   var a = 200;
    10      fn();
    11 }
    12 F2(f1);  // 100

    3.将函数与其所操作的某些数据关联起来,通常,你使用只有一个方法的对象的地方,都可以使用闭包

    1 // 改变dom样式
    2 document.getElementById("a").onclick = setSize(12);
    3     document.getElementById("b").onclick = setSize(18);
    4     document.getElementById("c").onclick = setSize(22);
    5     function setSize(fontSize){
    6         return function(){
    7             document.body.style.fontSize = fontSize + 'px';
    8         }
    9     }

    4.用闭包模拟私有方法

     1 //这三个公共函数是共享同一个环境的闭包。多亏 JavaScript 的词法作用域,它们都可以访问 privateCounter 变量和 changeBy 函数。
     2 var makeCounter = function () {
     3         var privateCounter = 0;
     4         function changeBy(val){
     5             privateCounter += val;
     6         };
     7         return {
     8             increment: function(){
     9                 changeBy(1);
    10             },
    11             decrement: function(){
    12                 changeBy(-1);
    13             },
    14             value: function(){
    15                 return privateCounter;
    16             }
    17         }
    18     };
    19     var Counter1 = makeCounter();
    20     var Counter2 = makeCounter();
    21     Counter1.increment();
    22     console.log(Counter1.value());//1 每次调用其中一个计数器时,通过改变这个变量的值,会改变这个闭包的词法环境。然而在一个闭包内对变量的修改,不会影响到另外一个闭包中的变量。
    23     console.log(Counter2.value());//0 以这种方式使用闭包,提供了许多与面向对象编程相关的好处 —— 特别是数据隐藏和封装。

    5.循环里面的闭包

    怎么才能实现输出0-5呢?

    1 for (var i = 0; i < 5; i++) {
    2   setTimeout(function () {
    3     console.log(i);
    4   }, 1000 * i);
    5 }//55555
    //方法一,makeCallback函数为每一个回调创建一个新的词法环境。
    function makeCallback(i) {
         return function() {
            console.log(i)
          };
        }
        for(var i=0;i<10;i++){
            setTimeout(makeCallback(i),1000)
        }
    //另一种方法使用了匿名闭包
    for(var i=0;i<10;i++){
            (function(i){
                setTimeout(function () {
                    console.log(i)
                },1000)
            })(i)
        }
    1 //使用let声明变量
    2 for (let i = 0; i < 5; i++) {
    3   setTimeout(function () {
    4     console.log(i);
    5   }, 1000 * i);
    6 }
  • 相关阅读:
    WCF HelpPage 和自动根据头返回JSON XML
    Jquery及插件 应用
    Autofac Mvc Webapi注入笔记
    TransactionScope 出错 与基础事务管理器的通信失败
    工厂方法模式(Factory Method)与抽象工厂模式(Abstract Factory)
    Asp.net的异步处理模型Asp.net的异步如何提高服务器的吞吐量
    WCF 契约定义命名空间 的疑问
    常用的18个人情世故
    StatusCode
    web标准常见问题集合
  • 原文地址:https://www.cnblogs.com/xiaole9924/p/11841497.html
Copyright © 2011-2022 走看看