zoukankan      html  css  js  c++  java
  • 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)
     
  • 相关阅读:
    数学+高精度 ZOJ 2313 Chinese Girls' Amusement
    最短路(Bellman_Ford) POJ 1860 Currency Exchange
    贪心 Gym 100502E Opening Ceremony
    概率 Gym 100502D Dice Game
    判断 Gym 100502K Train Passengers
    BFS POJ 3278 Catch That Cow
    DFS POJ 2362 Square
    DFS ZOJ 1002/HDOJ 1045 Fire Net
    组合数学(全排列)+DFS CSU 1563 Lexicography
    stack UVA 442 Matrix Chain Multiplication
  • 原文地址:https://www.cnblogs.com/hacker-caomei/p/14168425.html
Copyright © 2011-2022 走看看