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

    我们先看下面一个例子:

    function fun(){
        var arr = [];
        for(var i = 0; i < 10; i++){
            arr[i] = function (){
                return i;
            }
        }
        return arr;
    }
    var fn = fun();
    console.log(fn[0]()) //10
    console.log(fn[1]()) //10

    可能以为会打印0,1。但结果却都是10。

    对这个问题我们可以用let定义i来解决

    将 var  i   改为   let  i   打印出来的就是 0,1

    但 let  有一些限制条件

    比如  如果我们需要在for循环的外面 打印 i   -> console.log(i),使用let的话就会报错,提示 i is not defined.

    因为 let 只在{}里面的部分有效。并且 let定义变量时需要在调用该变量的前面,并不会将变量声明提前。

    也可以通过闭包来解决

    首先我们先了解什么是闭包(通俗易懂的)

    我们知道在js中 可以在子级访问父级中定义的变量,但不能在父级中访问子集的变量。

    这是作用域与作用域链造成的。

    下面我们来粗略了解一下作用域链

    作用域链

    作用域链是一个对象列表或者链表,这组对象定义了这段代码“作用域中”的变量

    当需要查找某个值时,从自身开始找,找不到就往父级找,依次往上找。都没有则报错

    作用域链上有两个对象,第一个时定义函数参数和局部变量的对象,第二个是全局对象。如果在嵌套的函数中,作用域上的对象数更多。

    基本方式是入栈排列。自身占第一个,后面是父级,再是父级的父级,依次,知道全局GO。

    值得注意的是,对于嵌套函数来说,每次调用外部函数时,内部函数又会重新定义一遍。所以每次调用外部函数时,内部函数的代码都是相同的,他们的作用域链不同。如下例子:

    function fun(){
        var num = 0;
        function jia(){
            num++;
            console.log(num);
        }
        function jian(){
            num--;
            console.log(num)
        }
        return [jia,jian];
    }
    var jia = fun()[0];
    var jian = fun()[1];
    jia()
    jian()

    打印结果是 1,-1.  而不是1,0.

    那我们想在父级中访问子集的变量,像这种内部函数的作用域链仍然保持着对父级函数活动对象的引用,就是闭包。

    通过上面的这个例子来说明:

    将代码改变一下:

    function fun(){
        var arr = [];
        for(var i = 0; i < 10; i++){
            (function(i){
                arr[i] = function (){
                    return i;
                }
            })(i)    
        }
        return arr;
    }
    var fn = fun();
    console.log(fn[0]()) //0
    console.log(fn[1]()) //1            

    这样使用闭包后就可以打印出 0,1 了

    当内部的函数被保存到了外面,就会形成闭包。

    但闭包也有自己的缺点:占内存。

    占内存:闭包导致原有的函数执行完成了以后作用域链不会得到释放,会占据大量的内存。

  • 相关阅读:
    奇异值分解(SVD)详解
    深度学习中常用的优化方法
    一年了,走了一些弯路,是时候回归了,介绍下深度学习中常见的降低过拟合的方法
    softmax与logistic关系
    Java [Leetcode 387]First Unique Character in a String
    Java [Leetcode 384]Shuffle an Array
    Java [Leetcode 167]Two Sum II
    用stack实现min stack
    bootstrap, boosting, bagging 几种方法的联系
    一道常被人轻视的前端JS面试题
  • 原文地址:https://www.cnblogs.com/ddjps/p/10139309.html
Copyright © 2011-2022 走看看