• js之闭包


    js中的闭包是一个比较常见的核心概念,之前我们讲的重载,函数柯里化中都用到了闭包,那么到底什么才是闭包呢,闭包能为我们干嘛呢?

    按照js犀牛书的定义,闭包是指函数变量可以保存在函数作用域内,这句话的意思貌似太笼统了,而且范围很广,一般的函数内都会包裹变量,那么也可以说有变量的函数就叫闭包吗?显然不是,我们看下js高程里的定义

    闭包是指有权访问另一个函数作用域中的变量的函数,这就是说访问外层函数变量的内层函数就叫作闭包咯。那么我们换一种意思理解,闭包是指那些在当前作用域上的函数或者变量被下层作用域所调用,那么我们先来看一个简单的闭包

     function a(){
                 var c= 2;
                 var b = function(){
                     console.log(c);
                 }
                 b();
             }
             a(); //输出2

    在上面的函数中,我们声明定义了一个a()函数,在函数里有个变量c ,该变量被内层函数b()使用输出,最后调用内层函数b();那按照上面的定义,因为在b的作用域内,调用了属于a作用域内的变量,所以形成了闭包。我们通过分析执行环境来看一下闭包的过程

            function foo(){
                 var a = 2;
                 function bar(){
                     console.log(a);
                 }
                 test(bar);
             }
             function test(fn){
                 fn();
             }
    foo();

    首先,进入全局执行环境,foo()和test()进行变量声明,然后进入第十行执行foo()函数,此时进入foo的执行环境

    首先a 和bar()先进行声明,然后执行第六行代码tes(bar) ,此时进入作用域链进行查询,查询test(),在全局作用域中找到test,然后进人test执行环境,然后执行bar,向上foo中查找bar,找到bar,然后执行console,此时console是全局自带的,在全局执行环境中找到,然后查找a,在foo执行环境中找到a,最后输出2;这样一来,我们就能很清楚的弄清楚闭包了,在局部函数中,变量通常会在函数执行后就会消失,但因为有闭包存在,闭包变量在别的作用域中被调用,所以a不会消失,成为自由变量,直到被再次找到,闭包会造成内存泄漏也是此原因。

    最后我们留一道题目给大家思考,看一下对闭包的理解是否到位

    for (var i=1; i<=5; i++) { 
        setTimeout( function timer() {
            console.log(i);
        }, i*1000 );
    }

    上面的代码会输出5个6,那么如何才能输出1,2,3,4,5呢? 这里提示一下,这里的for循环在执行时会生成5个定时器,然后定时器在沿着作用域链上去查找i,而此时的i的值可能跟你预想不一样,这里需要用到闭包来做。

    下回给大家讲下作用域。

  • 相关阅读:
    POJ 1330 Nearest Common Ancestors (LCA,dfs+ST在线算法)
    BZOJ 2002: [Hnoi2010]Bounce 弹飞绵羊 (动态树LCT)
    HDU 4010 Query on The Trees (动态树)
    SPOJ 375. Query on a tree (动态树)
    BZOJ 2049: [Sdoi2008]Cave 洞穴勘测 (动态树入门)
    HDU 3726 Graph and Queries (离线处理+splay tree)
    POJ 3580 SuperMemo (splay tree)
    Android中visibility属性VISIBLE、INVISIBLE、GONE的区别
    mysql如何在一张表中插入一万条数据?(用存储过程解决)
    Gradle Build速度加快方法汇总
  • 原文地址:https://www.cnblogs.com/maoxiaodun/p/10048615.html
Copyright © 2020-2023  润新知