zoukankan      html  css  js  c++  java
  • JavaScript-----11.预解析

    1.预解析

    1.1引子

    //1问
    console.log(num);//报错 num未定义
    
    //2问
    console.log(num); //undefined  未报错
    var num = 10;
    
    //3问
    fun();//11 未报错
    
    function fun() {
        console.log(11); 
    
    }
    //把fun();放在后面、前面都不会报错
    
    //4问
    fun1();//报错 fun1 is not a function
    var fun1 = function() {
            console.log(22); 
    
        }
        //把fun1();放在后面就不会报错
    
    
    //综上,问2和文4都比较奇怪
    
    1. Js代码是由浏览器中的js解析器来执行的。js解析器在运行js代码的时候分为两步:预解析和代码执行。
    • 预解析:js引擎会把js里面所有的var、function(这里指函数声明,不包括函数表达式)提升到当前作用域的最前面。
    • 代码执行:按照代码书写的顺序从上往下执行

    2.变量预解析和函数预解析

    预解析分为变量预解析(变量提升)和函数预解析(函数提升)

    2.1 变量提升 就是把所有的变量声明提升到当前作用域的最前面,不提升赋值操作。

    对于之前的“问2”

    //2问
    console.log(num); //undefined  未报错
    var num = 10;
    

    相当于执行了以下代码

    var num;
    console.log(num); //undefined
    num = 10;
    

    对于之前的“问4”

    //4问
    fun1();//报错 fun1 is not a function
    var fun1 = function() {
            console.log(22); 
    
        }
    //把fun1();放在后面就不会报错
    

    相当于执行了以下代码

    var fun1;
    fun1();//报错 fun1 is not a function
    fun1 = function() {
        console.log(22);
    
    }
    

    值得注意的是这里的fun1是变量名,不是函数名,这里是函数表达式,是匿名函数。

    2.2 函数提升 就是把所有的函数声明(注意是函数声明,不是函数表达式)提升到当前作用域的最前面, 不调用函数。

    这就可用说明为什么在“问3”中,函数的fun();放在前后都不会报错,对于之前的问“问3”

    fun();//11 未报错
    
    function fun() {
        console.log(11); 
    
    }
    

    相当于执行了以下代码

    function fun() {
        console.log(11); 
    
    }
    fun();//11 未报错
    

    注意:由于函数表达式无法进行函数提升,所以函数表达式的调用必须写在函数表达式的下面

    3.预解析案例

    //案例1 会输出什么
    var num = 10;
    fun();
    
    function fun() {
        console.log(num); 
        var num = 20;
    
    }
    

    相当于执行了以下代码

    var num;
    
    function fun() {
        var num;
        console.log(num); //undefined
        num = 20;
    
    }
    num = 10;
    fun();
    
    //案例2
    var num = 10;
    
    function fn() {
        console.log(num);
        var num = 20;
        console.log(num);
    }
    fn();
    

    相当于执行了以下代码

    //相当于执行以下代码
    //由内而外地完成变量提升,在根据链式查找法,得到输出的结果
    var num;
    
    function fn() {
        var num;
        console.log(num); //undefined
        num = 20;
        console.log(num); //20
    }
    num = 10;
    fn();
    
    //案例3
    var a = 18;
    f1();
    
    function f1() {
        var b = 9;
        console.log(a);
        console.log(b);
        var a = '123';
    }
    

    相当于执行了以下代码

    //相当于执行了以下代码
    var a;
    
    function f1() {
        var b;
        var a;
        b = 9;
        console.log(a); //undefined
        console.log(b); //9
        a = '123';
    }
    a = 18;
    f1();
    

    小tips:

    var a = b = c = 9;
    

    相当于

    var a=9;
    b=9;
    c=9;
    

    集体声明

    var a = 9,b = 9,c = 9;
    

    才相当于

    var a = 9;
    var b = 9;
    var c = 9;
    
    //案例4
    f1();
    console.log(c);
    console.log(b);
    console.log(a);
    
    function f1() {
        var a = b = c = 9;
        console.log(a);
        console.log(b);
        console.log(c);
    }
    

    相当于执行以下代码

    //相当于执行以下代码
    function f1() {
        var a;
        a = b = c = 9;
        console.log(a); //9
        console.log(b); //9
        console.log(c); //9
    }
    f1();
    console.log(c); //9
    console.log(b); //9
    console.log(a); //报错 a is not defined
    

    案例总结:先将代码按照预解析排列好,再按照作用域链去查找结果即可。

  • 相关阅读:
    无法设置 / 添加网络打印机?报错 无法保持设置?
    tp剩余未验证内容-5
    再谈 iptables 防火墙的 指令配置
    tp剩余未验证内容-4
    tp剩余未验证内容-3
    CentOS7.4安装配置mysql8 TAR免安装版
    CentOS7中systemctl的使用与CentOS6中service的区别
    CentOS下如何查看并杀死僵尸进程
    CentOS SVN服务器管理多项目
    swoole+Redis实现实时数据推送
  • 原文地址:https://www.cnblogs.com/deer-cen/p/12039715.html
Copyright © 2011-2022 走看看