千锋教育-做有情怀、有良心、有品质的职业教育机构

手机站
千锋教育

千锋学习站 | 随时随地免费学

千锋教育

扫一扫进入千锋手机站

领取全套视频
千锋教育

关注千锋学习站小程序
随时随地免费学习课程

当前位置:首页  >  技术干货  > 深度解析Javascript中的变量提升

深度解析Javascript中的变量提升

来源:千锋教育
发布人:wjy
时间: 2022-06-02 14:12:00 1654150320

> 大家好,我是前端老陈醋,有关js中的变量提升,很多小伙伴可能都会有疑问,尤其是面试的过程中有大量有关于变量提升相关的题,那么浏览器在解析js的过程中,js中的变量究竟是怎么提升的呢?想要彻底解决这些问题,就要理解浏览器是怎么解析js代码的,那么我们今天就来深度解析一下这个问题哈。

深度解析Javascript中的变量提升

## 首先在JS中涉及两种作用域的问题,那么什么是作用域呢?

> 作用域是代码中所使用名字的作用范围,分为Script全局作用域和函数局部作用域。 当浏览器在解析网页内容时,会分别启动不同的解析器来解释代码的含义,如解析标签(超文本)的解析器、解析CSS样式的解析器,解析javascript脚本的解析器。且解析过程为同步(按顺序)解析。所以当浏览器解析到script标签时,会停止对html和css的解析,同时启动javascript的解析器。而在解析javascript的过程中我们主要关注解析器中的两个步骤:

1. 预解析,即在当前作用范围中去寻找var、function、形参这三个内容。

- 如果找到var关键字、则提取var后面的名字放到当前作用域中,且默认给这个变量初始化一个值为undefined。
- 如果找到function关键字,则提取函数名放到当前作用域中,且将整个函数块赋值给函数名。
- 如果找到形参,则将形参名放到当前作用域中,且默认初始化为undefined。这个过程也称为变量提升。

\2. 逐行解读代码(即从上到下依次执行每一条语句)且分为两个步骤:

- 执行表达式
- 函数调用。

```js
/*
        一、预解析(寻找var function 形参)
            i = undefined (进入script作用域时,找到var)
            fn = function fn(){alert(2);}  (进入script作用域时,找到function)
        二、逐行解读代码(函数声明,直接跳过)
            1. 执行表达式
            2. 函数调用
    */
    alert(i); //1. 当执行第一个表达式时,输出i的值为undefined
    //第一个找到的是var,所以将i放到预解析中,初始化为undefined
    var i = 1; //2. 当执行第二个表达式i = 1时,会在预解析中先找到变量i,将值修改为1
    alert(i);//3. 当执行输出表达式时,在预解析中i的值 1 输出
    function fn(){ //4. 函数声明,不执行,直接跳过
        alert(2);
    }
    alert(i); //5. 当执行输出表达式时,在预解析中i的值 1输出
```

> 当变量名与函数名相同时:

```js
/*
        一、预解析(寻找var function 形参)
            a = undefined  (在作用域中第一次找到var a) (在找到同名的函数a时,当前变量a被丢弃)
            a = function a(){alert(2);}   (在作用域中第二次找到 function a,所以在作用域同时出现一个变量a和一个函数a,此时,将变量a丢弃,保留函数a) (在找到下一个function a时,此时的函数 a 被覆盖)
            a = function a(){alert(4);}   (在作用域中第三次找到function a时,与前面是相同的函数 a,会将前面的函数a 进行覆盖)
            a = 1   (当执行到a = 1时,上面的a = function a(){alert(4);} 将被覆盖成 1)
        二、逐行解读代码(函数声明,直接跳过)
            1. 执行表达式
            2. 函数调用
    */
    alert(a);  // 1. 在执行该表达式时,预解析中只有 a = function a(){alert(4);} 所以此时的结果为   function a(){alert(4);}
    var a = 1;  // 第一次找到的 var a
    alert(a); //2. 在执行该表达式时,预解析中的 a 值为 1 ,所以结果为  1
    function a(){ //第二次找到的 a
        alert(2);
    }
    function a(){  //第三次找到的  a
        alert(4);
    }
    alert(a);  // 3. 在执行该表达式时,预解析中的 a 值为 1 ,所以结果为  1
```

> 当有多个script标签时: - 多个script标签时,从上到下依次解析script作用域,所以建议将所有声明的语句放到第一个script中。

```html
<script>
        /*
            一、预解析(寻找var function 形参)
                fn = function(){alert(2);} (在解析第一个script时,只找到一个funciton fn);

                a = 1  (在解析第二个script作用域时,找到 var a)
            二、逐行解读代码(函数声明,直接跳过)
                1. 执行表达式
                2. 函数调用
        */
        alert(a); //报错,在执行该表达式时,因为在预解析中没有a变量,所以此时会报错。
        function fn(){
            alert(2);
        }
    </script>
    <script>
        var a = 1;
        fn(); //2   在调用该函数时,在预解析中已经存在function fn,所以输出函数中的表达式 值为2
    </script>
```

更多关于“web前端培训”的问题,欢迎咨询千锋教育在线名师。千锋已有十余年的培训经验,课程大纲更科学更专业,有针对零基础的就业班,有针对想提升技术的提升班,高品质课程助理你实现梦想。

tags:
声明:本站稿件版权均属千锋教育所有,未经许可不得擅自转载。
10年以上业内强师集结,手把手带你蜕变精英
请您保持通讯畅通,专属学习老师24小时内将与您1V1沟通
免费领取
今日已有369人领取成功
刘同学 138****2860 刚刚成功领取
王同学 131****2015 刚刚成功领取
张同学 133****4652 刚刚成功领取
李同学 135****8607 刚刚成功领取
杨同学 132****5667 刚刚成功领取
岳同学 134****6652 刚刚成功领取
梁同学 157****2950 刚刚成功领取
刘同学 189****1015 刚刚成功领取
张同学 155****4678 刚刚成功领取
邹同学 139****2907 刚刚成功领取
董同学 138****2867 刚刚成功领取
周同学 136****3602 刚刚成功领取
相关推荐HOT