• 词法作用域,作用域链


    1.函数声明和函数表达式的区别

    function foo(){}

    var foo=function(){}

    1.上面的语法是声明,可以提升,因此在函数定义的上方也能调用该函数

    2.下面的语法是函数表达式,函数名是foo,它会提升,提升的不是函数体

    3.函数表达式也支持名字语法

    function foo(){
    }
    console.log(foo.name);//foo

    **函数有一个属性name,表示的是函数名。函数声明的函数定义的属性值name就是该函数名,如果是函数表达式定义的函数定义,如果后面没有带函数名的,默认是函数表达式变量的值,如果后面带了函数名那么name属性值就是该函数名。函数声明能够直接使用name属性值,但是函数表达式不能在函数表达式之外使用函数的name属性,只能在函数表达式里面使用函数的name属性值。

    //函数声明
    function foo(){
    };
    foo.name;//结果是foo
    foo;//结果返回整个foo的函数体
    
    
    //函数表达式
    var foo1=function (){} //默认的是foo1.name就是foo1
    
    var foo2=function bbb(){}
    //foo2.name就是bbb,但是这种函数表达式的函数定义的name属性值不能在外部直接使用。
    //bbb  //返回的bbb is not defined
    
    var foo3=function bbb(){
      console.log(bbb);   //这里能使用函数的name属性值     
    }
    
    foo3();//输出bbb的函数体

    注意:

    在新的浏览器中,包含在逻辑判断(if,while)里面的函数声明会被转换成特殊的函数表达式(函数声明的变量会提升,函数表达式的变量不会提升);

    看一下例子

    //如果是谷歌,火狐等主流浏览器
    
    if(true){
       function fun1(){console.log(123)}  
    }else{
      function fun1(){console.log(456)}  
    }
    
    fun1();//结果123;
    if(true){
       function fun1(){console.log(456)}  
    }else{
      function fun1(){console.log(123)}  
    }
    
    fun1();//结果456;
    
    /*代码解析,按照javascript的预编译解析,一步一步走下来。因为函数声明包含在if这种逻辑判断里面,所以是特殊的函数表达式,不会发生变量提升。
    if(true)->声明fun1,然后执行fun1,所以结果是输出123;*/
    
    //如果是在IE8以下这种浏览器
    if(true){
       function fun1(){console.log(123)}  
    }else{
      function fun1(){console.log(456)}  
    }
    /*
       代码解析:包含在逻辑判断里面的函数声明还是函数声明,会发生变量提升,fun1声明,fun1覆盖前面这个声明 ,所以不管是条件是true或者是false,最后调用fun1()输出的结果都是456;
    */

    2.词法作用域

    *****

    作用域:在js中出现域表示的就是范围,即作用范围。就是一个名字可以在什么地方使用,不可以在什么地方使用。

    在c,java等语言中,花括号表示的是块级作用域

      伪代码(仅仅用于描述意思即可)

      {  

        var name=123;

        {

          console.log(name);//输出结果:123

        }

      }

          console.log(name);//作用域之外访问name,表示的是name is undefined

    ******

    词法作用域:所谓词法(代码)作用域,就是代码在编写过程中体现出来的作用范围,代码一旦写好了,没有运行之前(不用执行),作用范围就已经确定好了,这个就是所谓的词法作用域。

     词法作用域的规则:

       1.函数允许访问函数外部的数据

              2.整个代码结构中只有函数才能限定作用域

              3.作用规则首先使用变量提升规则分析

              4.如果当前作用规则里面有该名字,则不考虑外面的外面的名字

    if(false){
      var num=123;  
    }
    console.log(num); //undefined
    
    /*
    代码说明:num变量发生了函数提升,首先定义了var num,但是由于false没有进入下面的var num=123的赋值操作,所以下面console.log(num)的时候显示undefined
    */
    var num=123;
    function foo(){
        var num=456;
        function func(){
             console.log(num);
        }
        func();  
    }
    
    foo();//结果输出:456;
    
    /*
    代码说明:首先最外面的num和foo发生了变量提升,执行foo()的时候,进入foo的作用域里面,num和func发生了变量提升,执行func()的时候,需要输出num,func里面没有num,需要外跳一级寻找num,如果这里面有num,则不查询外面的num了。
    */

     3.作用域链

    绘制规则

    (1)全局变量,函数申明都是属于0级链,每个对象占一个位置

      (2)凡是看到函数就延伸一个链出来,一级级展开

      (3)访问首先看到当前函数,如果当前作用域链没有定义,往上级链中检查

       (4)如此往复,直到0级链,如果0级没有,则弹出错误,这个变量没有定义

    var num=10;
    var func1=function(){
         var num=20;
        var func2=function(){
            var num=30;
            alert(num);  
        };
        func2();  
    }
    
    func1();//结果弹出:30

    绘制作用域链,代码分析也标注在图上

    以下这段代码值得好生体会一下:

    function func1(){
       alert(num);  
    }
    
    function func2(){
       var num=456;
       function func3(){
           func1();
       }
       func3();  
    }
    
    func2();//结果显示:num is not defined

    绘制作用域链,代码步骤分析标注在图上

  • 相关阅读:
    REHの个人主页
    多项式基础学习笔记(2)
    多项式基础学习笔记(1)
    FFT & NTT 学习笔记
    LCT学习笔记
    莫队学习笔记
    SAM 学习笔记
    网络流学习笔记
    关于魔术球贪心做法的证明
    【题解】异或粽子&加强版
  • 原文地址:https://www.cnblogs.com/liyusmile/p/8855979.html
Copyright © 2020-2023  润新知