zoukankan      html  css  js  c++  java
  • 20-作用域及预解析

    一、函数作用域

    作用域是一个变量或函数的作用范围。作用域在函数定义时,就已经确定了。
    作用域的内部原理 
    编译、执行、查询、嵌套、异常

    • 编译:边解释,便运行
      • 分词单元
      • 解析成抽象树
        //编译:
          //1.分词:var,a,=,10
          /*
              {
                'var':'keyword',//关键字
                'a':'indentifier',//标识符
                '=':'assignment',//分配
                '2':'interger',//整数
                ';':'eos',结束语局
              }
          */
          //2.解析
          //抽象语法树
    
    全局作用域与局部作用域
    • 全局作用域:作用于整个 script 标签内部,或者作用域一个独立的 JS 文件
    • 局部作用域:作用于函数内的代码环境
    作用域链

    当在函数作用域操作一个变量时,它会先在自身作用域中寻找,如果有就直接使用(就近原则)。如果没有则向上一级作用域中寻找,直到找到全局作用域;如果全局作用域中依然没有找到,则会报错。

        var i = 1//最后来全局找
        function a(){
          var i = 2
          //再来它最近的父级找
          function b(){
            i++//先在内部找
            console.log(i)//3
          }
          b()
        }
        a()
        
    
    全局变量与局部变量
    • 全局变量:在全局作用域下面 声明 的变量,在script标签内所有的地方都可以访问和修改
    • 局部变量:在函数内部 声明 的变量,收到函数作用域的保护,只能在当前作用域访问
      • 两者生命周期
      • 全局变量:只有浏览器关闭时才会被销毁,比较占内存。
      • 局部变量:当其所在的代码块运行结束后,就会被销毁,比较节约内存空间。

    函数的形参是局部变量

      <script>
        function foo(a) {
          return a + 6;
        }
        var res = foo(1);
    
        console.log(res);//7
        // 函数的形参是一个局部变量,全局中无法访问
        console.log(a);// a is not defined
      </script>
    

    js中没有块级作用域

      <script>
        // js中没有块级作用域
        if (true) {
          var num = 123;
          console.log(num); //123
        }
    
        console.log(num); //123(可以正常打印)
    
        // 全局变量和局部变量仅存在函数中
        function fn() {
          var num1 = 123;
          console.log(num1);
        }
    
        console.log(num1);//num1 is not defined
      </script>
    

    js函数调用栈

      <script>
        function a(){
          console.log('a')
        }
        function b(){
          console.log('b')
          // 函数内部的代码还是按顺序执行的,遇到新的函数执行才会进行压栈操作
          a()
          console.log('b1')
        }
        function c(){
          console.log('c')
          b()
          console.log('c1')
        }
        // 在函数执行的时候会将该函数压入到执行栈里面,当函数代码执行的时候又遇到了函数执行语句,那么当前函数执行
        // 上下文暂停,将新函数压入栈中...当函数执行完毕以后会发生出栈操作,函数的执行上下文交回给紧挨着    
    		// 它的底下的函数
        c() // c b a b1 c1
    

    js中没有动态作用域,是词法作用域

      <script>
        // js的作用域是词法作用域/静态作用域,而不是动态作用域!!!!
        // 函数作用域的形成是在函数声明的时候就决定好了的,而不是在调用的时候
        var i = 0
        function a(){
          console.log(i)
        }
    
        function b(){
          var i = 1
          a() // 0
        }
        b()
      </script>
    

    二、函数的预解析

    js在执行时,会将变量的声明和函数的声明解析到代码的最前面。

      <script>
        // 源代码
        var a = 1;
        var b = function () {
        }
        function d() {
        }
    
        // 预解析后
        var a;
        var b;
        function d() { }
        b = function () { }
        a = 1;
      </script>
    

    函数是js中国的一等公民!当变量和函数同名时,解析时,只会执行函数

    小练习
        var num = 10;
        fn1();
        function fn1() {
          console.log(num); // undefined
          var num = 20;//会在当前的函数作用域里面预解析
        }
    
        <script>
            // 先预解析变量a个函数aaa,bbb
            // 由三个aaa重名,所以最后一个会覆盖前两个,整个html只有第三个aaa和bbb生效
            // bbb中虽然var a= 40,但是调用的是aaa,aaa弹出的a的值访问不到函数bbb里面,所以是30
            var a = 10;
            function aaa() {
                alert('1' + a);
            };
            aaa();//310
    
            function aaa() {
                var a = 20;
            };
            aaa();//310
            alert('2' + a);//210
    
            var a = 30;
            function aaa() {
                alert('3' + a);//330
            };
            function bbb() {
                var a = 40;
                aaa();
            }
            bbb(); 
        </script>
    
        <script>
            function aaa() {
                a = 10;
            }
            aaa();
            alert(a);//undefined
    
            var a;//变量只声明不赋值,打印就是undefined
    
            function aaa() {
                var a = b = 10;
                // 解析为var a = 10, b = 10
                // 此时a是局部变量,b没有声明,是全局变量
            }
            aaa();
            alert(a);//undefined
            alert(b);//10
        </script>
    
        fn3();
        console.log(c); // 9
        console.log(b); // 9
        console.log(a); //  a is not defined
        function fn3() {
          var a = b = c = 9;
          console.log(a); // 9
          console.log(b); // 9
          console.log(c); // 9
        }
    
        a();
        function a() {
          console.log(1);//1
        }
        var a = 1;//将1赋值给a,此时a里面装的就是数,无法被调用~
        a(); // a is not a function
        console.log(a); // 压根不执行
    
        var n1 = 11;
        var n2 = 22;
        fn2();
        fn();
        function fn() {
          var n1 = 111;
          n2 = 222;//修改了全局里面的n2
          var n3 = 333;
          console.log(n1, n2, n3);//111,222,333
        }
    
        function fn2() {
          n1 = 1111;//修改了全局里面的n1
          var n2 = 2222;
          var n3 = 3333;
          console.log(n1, n2, n3);//1111,2222,3333
        }
        console.log(n1, n2);//1111,222
        console.log(n3);//n3 is not defined
    
      <script>
        if (true) {
          function foo() {
            console.log(true);
          }
        } else {
          function foo() {
            console.log(false);
          }
        }
        foo();
      </script>
    
      <script>
        console.log(a);//undefined
        a();//a is not a function
        var a = 3;
        var a = function () {
          console.log(10);
        }
        console.log(a);
        a = 6;
        a(); 
      </script>
    
        var num1 = 111;
        var num2 = 222;
    
        function fn(num1) {
          //函数的形参就是一个局部变量
          //预解析 var num1;
          num1 = 333;
          num2 = 444;
          console.log(num1); // 333
          console.log(num2); // 444
        }
    
        fn(num1, num2);
    
        console.log(num1); // 111
        console.log(num2); // 444
    
  • 相关阅读:
    python第三方库requests详解
    英语单词Permissive
    Linux系统重要文件(三)
    Linux系统重要文件(二)
    Linux系统重要文件
    操作系统挂载
    Linux系统基础优化
    系统软件安装
    MYSQL二进制安装
    MySQL基本操作
  • 原文地址:https://www.cnblogs.com/xiaoaitongxue/p/12796846.html
Copyright © 2011-2022 走看看