【JavaScript】预解析

本文详细解读JavaScript中预解析的两个关键步骤:变量提升和函数优先级。通过实例演示了预编译期间如何处理var声明、函数声明与重名情况,以及执行期函数调用的特性。重点讲解了预编译如何影响代码执行和变量行为。
摘要由CSDN通过智能技术生成

预解析

💡 Tips:

  1. 为什么要学习预解析?
  2. 为什么变量具有变量提升, 同时输出undefined?
  3. 为什么"声明式函数"可以在任意地方进行调用?
console.log(a); //undefined
    var a = 1;
    console.log(a); //1
    // 为什么声明式函数可以在任意地方进行调用?
    fn();

    function fn() {
        console.log(1);
    }
    fn();

一、解读预解析的两个步骤

1.预编译期

预编译: 代码进入浏览器执行之前干的事情(不可见)

  • 先找var和function关键字,找到var,提前赋值undefined。找到function,提前将整个函数体赋值给函数名。
  • 如果预编译函数和变量名出现重复,函数优先(干掉变量名)。
  • 函数内部依然做预编译,同时函数的参数类似函数内部的变量,也要做预编译。

2.执行期(代码逐行执行)

逐行执行:代码进入浏览器,可以根据浏览器返回的信息,查看结果,同时遇到代码错误,立刻停止执行。

  • 函数声明直接跳过,函数必须调用才有意义

💡 Tips:
接下来通过几个案例逐一分析预编译的每一种情况和执行期的整个步骤

案例一

//第一步: 分析预编译的结果:提前进入浏览器的引擎(整个预编译的过程不可见!)
//var a = undefined //由于预编译规则,找到var,提前赋值undefined给变量
//fn = function fn() {console.log(‘函数’);} //由于预编译规则,找到undefined,提前将整个函数体赋值给函数名
//第二步: 进入逐行执行。(代码逐行执行)

//第一步: 分析预编译的结果:提前进入浏览器的引擎
    //var a = undefined
    //fn = function fn() {console.log('函数');}

//第二步: 进入逐行执行。
    console.log(a); //undefined
    fn();
    var a = 10; //这里将预编译的结果10赋值给变量a = 10
    console.log(a); // 10
    function fn() {
        console.log('函数');
    }
    fn();

案例二

//第一步: 还是先分析预编译的结果:注意这里的变量名与函数名重名,所以函数名优先(提前将整个函数体赋值给函数名),因此console.log(a)输出的是函数体function a() {console.log(‘函数’);}
//第二步: 进入逐行执行。(代码逐行执行)
注意在代码正常执行的过程中,遇函数声明会直接跳过,因为函数必须是调用才有意义

console.log(a); //function a() {console.log('函数');}
    var a = 10; //修改预编译的结果: a = 10
    console.log(a); //10

    function a() {
        console.log('函数');
    }
    console.log(a); //10

案例三

// 变量的访问

// 变量的访问
    var a = 10;
    function fn() {
        var b = 10; //函数里面的变量外面无法获取的。
        console.log(a); //10,函数内部可以访问函数外面的变量,但是如果变量函数内部存在,优先使用内部的
    }
    fn();
    console.log(b);

// 分析函数内部预编译的结果:提前进入浏览器的引擎
// a = undefined
// 注意:只要函数存在形参,一定要做预编译。

 // 分析函数内部预编译的结果:提前进入浏览器的引擎
 //    a = undefined
 //    注意:只要函数存在形参,一定要做预编译。
    var a = 10;

    function fn(a) { //函数的参数相当于函数内部的变量,要做预编译  var a = 10  
        console.log(a); //10
        a = 20;
        console.log(a); //20
    }

    console.log(a); //10

    fn(a);


// var a = 10;
    // function fn() { //注意:此时的函数内部无需做预编译,不存在var和function
    //     console.log(a);
    //     a = 20;
    //     console.log(a);
    // }
    // fn();

案例四(重点掌握)

// 第一步: 预编译:
// var a = undefined
// a = function a() {alert(5);}
// 预编译重名,最终的预编译结果:
// a = function a() {alert(5);}
// 第二步: 逐行执行

// 1.预编译:  先找var和function,变量与函数名重名,函数优先。
//又由于两个函数名也是重名,后面的函数优先赋值
    // var a = undefined
    // a = function a() {alert(5);}
    // 预编译重名,最终的预编译结果:
    // a = function a() {alert(5);}

// 2.逐行执行
alert(a); // function a() {alert(5);}
    a(); //5
    var a = 3; //a = 3

    function a() {
        alert(10);
    }
    alert(a); //3

    function a() {
        alert(5);
    }
    a = 6; //a = 6
    alert(a); //6
    var a = function() { //a = function() {//a =  alert(8);}
        alert(8);
    }
    a(); //8

案例五

//预编译,后面的add优先
    // 使用的add函数里面没有return,整个函数返回的一定是undefined
    var x = 12345;
    var y = 67890;
    var z = 123456789;

    function add(n) {
        n = n + 1;
        return n;
    }
    y = add(x);
    console.log(y); // undefined

    function add(n) {
        n = n + 3;
    }
    z = add(x);
    console.log(z); // undefined
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

芒果Cake

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值