• js作用域链,js闭包


    一 预编译

     1概念

      1)什么是预编译: 

      2)全局对象(Global)GO window 

        全局变量

        全局函数

      3)活动对象AO local 

        局部变量

        局部函数

    2 全局预编译

      1) 流程:1找变量声明作为Go对象的属性名,值为undefined。2找函数声明,作为Go对象的属性值,值为function。

      var a;变量声明
    
      function a(){}; 函数声明;

    流程:

      (1)先把所有scirpt标签过一遍,然后整合在一起。

      (2)全局预编译

        1 产生window对象。GO

        2 查找变量的声明,把a最为window对象的属性名,属性值为undefined。

        3 查找函数的声明,把函数名a作为window对象的属性名,属性值是function

      (3)全局预编译结束后,从上到下,依次执行代码。

    3函数预编译:

      1)流程:

      1函数被调用的时候,为当前函数产生AO对象。

      2 查找形参和变量作为AO对象的属性名,作为undefined

      3 使用实参值改变形参的值。

      4 查找函数声明,作为AO对象的方法,值为function。

    test是AO对象的形参,i是AO对象的属性,b是AO对象的方法。

    // 当调用函数a的时候,生产函数a的AO对象。进入函数预编译。

    //AO:1 查找形参test,变量i作为i的AO对象属性名,值为undefined。

    //  2形参‘1’赋值赋值给test。test:1

    //  3查找局部函数 b,b作为AO对象的属性名,值为function。

    function a(b,c){
    console.log(b)
    var b=0;
    consoel.log(b)
    function b(){
    console.lgo(22)
    }
    console.log(c);
    }
    a(1)

    a:AO{

    b:fun,

    c:undefinde.

    }

    function a(i){
    
    var i;//在预编译阶段就执行了,正式阶段不会执行。
    
    console.log(i)//i=1;
    }
    a(1);

    一般来说优先级:

    局部函数>实参>形参。

    总结:1找声明;2 找赋值和调用。3 调用函数 进行AO对象,进行,函数作用域分析。

    4找声明 形参 和变量为undefined 5赋值形参。找函数什么。6 找赋值和找调用。

    二 作用域 和作用域链

    1概念

      1)域

      全局作用域:有<script>标签产生的区域,从计算机的角度可以理解为window对象。

      局部作用与:由函数产生的区域。从计算机的角度理解:函数的AO对象。

    ES6之前,没有块作用域。

      2)作用域链

      函数存在一个隐士属性,[scopes],也称为作用于链,我们可以把它理解称为一个数组。

    分析1)当在函数a外部的时候,作用域只有一个。就是Global

     

    当在函数a内部的时候, 作用域下有两个,一个是local,一个Global。

    当然我们看,当只有一个函数的时候,它的作用域是什么。(console.dir(a)打印a的内部属性)

    分析2)

        function a(){
            console.dir(a);
            function b(){
                console.dir(b);
                function c(){
                    console.dir(c);
                }
                c();
            }
            b();
        }
        a();

    0产生全局作用域

    1产生a函数的AO对象,aAO

    函数a的scopes:

      0:aAO

      1:GO

    2 产生b函数的AO对象,bAO

     3产生c函数的AO对象。

     

     

    2作用

    作用域链的查找规则:

    function a(){
      var aa=111
      function b(){
      var aa=222
      console.log(aa)}
      b()
    } a();

    1 产生a的AO对象,aAO

    aAO:{ aa:111,b:fun}

    2 产生b的AO对象,bAO

    bAO:{aa:22}

    在内部可以使用外部的函数,但是外部使用不了内部。因为b的AO对象没有产生。

    三 闭包

    视频:https://www.bilibili.com/video/BV1C54y1r7VS?p=13

    博客:https://www.cnblogs.com/sandaizi/p/11582488.html

    1外包的形成:

     内部函数使用外部函数的变量,就是形成闭包。闭包是当前作用域的延伸。

    案例1

    function a(){//外部函数
      var aa=111
      function b(){ //内部函数
      console.log(aa)}//aa是外部函数的变量,立刻,产生闭包。但是闭包并没有保存下来
      b()
    }
    a();

    案例2

    function a(){
    var aa=100
    function b(){
    console.log(b);}//形成闭包,{b:fun},但是结束被销毁了指针引用销毁了,
    b()
    }
    a();

    案例2

    function a(){
    var aa=100
    function b(){
    var aa=10;
    console.log(aa);}// 不会形成闭包。因为,没有引用外部函数的变量
    b()
    }
    a();

    2 闭包的保持:(真正形成闭包,且不会消失!)

    案例三:

        function outerFunction() {
            var num = 0;
            function inner() {
                console.log(num++);
            }
            return inner;//inner就是一个闭包函数,因为可以访问到outerFcuntion的作用域。
        }
        var  demo = outerFunction();
        console.log(demo);
        demo();
        demo();

    闭包产生的条件:
    //闭包要形成:1内部函数使用外部函数的变量。
    //闭包要保持:2 把内部函数返回到外部函数的外面。这样闭包才不会消失!!!

    四 闭包的应用:

    1闭包的两面性:

    好处:一般来说,函数外部是不能访问函数内部的变量。也就是设计闭包。

    坏处: 不注意使用闭包,出现奇怪的效果。

    (1)《JavaScript高级编程》由于闭包会携带包含它的函数的作用域,因为会比其他函数占用更多内容,过度使用闭包,会导致内存占用过多。并不会垃圾回收。而且因为作用域链的原因。所有内存占用多。

    (2)闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。

    2 闭包的作用:

    1 函数外部访问私有变量:

    2 实现封装。

    3 防止污染全局函数。

        function Person() {
            var uname
            function setName(uname) {
                this.name = uname
            }
            function getName() {
                return this.uname
            }
            return {
                getName: getName,
                setName: setName,
            }
        }
        var xiao = new Person()
        console.dir(xiao)
        xiao.setName('xiaoli')
        console.log(xiao.getName)
     
  • 相关阅读:
    bzoj 1497 最小割模型
    bzoj 1024 暴力深搜
    POJ1163(简单的DP)
    POJ3287(BFS水题)
    N皇后问题(DFS)
    BFS求解迷宫的最短路径问题
    poj2386(简单的dfs/bfs)
    Fence Repair(poj3253)
    Best cow Line(POJ 3617)
    全排列
  • 原文地址:https://www.cnblogs.com/hacker-caomei/p/14168425.html
Copyright © 2020-2023  润新知