美文网首页前端开发那些事让前端飞
关于JavaScript变量提升那点事儿

关于JavaScript变量提升那点事儿

作者: MonkeyDwwl | 来源:发表于2017-08-14 10:18 被阅读0次

    ECMAScript在浏览器端运行被称为JavaScript

    在浏览器端JavaScript是一种描述型脚本语言,不需要编译成中间语言,而是由浏览器按代码块顺序进行动态地解析与执行。

    关于作用域

    ES6之前,只有全局作用域和函数作用域;ES6引入了块级作用域。作用域是代码执行过程中的变量、函数或者对象的可访问区域。

    • 全局作用域:当定义变量的地方没有被 function 包括则是全局变量
    • 函数作用域:在函数内部定义的变量就是处于函数作用域中
    • 块状作用域:类似于 if、switch 条件选择或者 for、while 这样的循环体即是所谓的块级作用域

    关于变量的生命周期

    变量的生命周期包含着变量声明、变量初始化、以及变量赋值三个步骤;其中声明步骤会在作用域中注册变量,初始化步骤负责为变量分配内存并且创建作用域绑定,此时变量会被初始化为 undefined,最后的分配步骤则会将开发者指定的值分配给该变量。

    关于预编译

    JavaScript代码不需要编译成一个其它可执行的文件,但是js代码在执行之前会有一个准备过程,这个准备过程叫作预编译。
    预编译的过程是不可见的,也不会产生额外的文件。

    预编译期间会主要完成两件事情:

    1. 按顺序扫码代码块,如果发现语法错误,停止工作并报错;
    2. 若没有语法错误,做声明变量和初始化变量的操作即所谓的变量提升操作;

    先看一道简单的题目

    <script type="text/javascript">
        console.log(a);
        var a = 666;
        console.log(a);
    </script>  
    

    这道题目很简单,但是却很能说明问题。

    提升操作

    • 使用var声明的变量的提升:把所有带有var关键字的变量名,提升到当前代码块的开始,并设初值为undefined。
    • 函数提升:把所有用声明式定义的函数,提升到当前代码块的开始,注意是做函数整体的提升。

    具体细节如下

    只提升加var的变量,没有var不提升


    如图,没有var,变量名没有提升,相当于没有声明变量a就直接使用它,会出现引用类型错误。

    if结构中的变量提升


    如图所示,变量提升一定是发生在预编译期(提升之后才会进入代码的执行期),而变量的提升与if条件语句是否成立无关。只要有var就会提升。

    for循环中的变量提升


    同样会做变量提升。

    函数内部的变量提升


    函数内部定义的变量,不可能提上到函数的外部。如图会直接报错。

    函数内部的变量只会体升到函数的开始位置。

    只提升声明式定义的函数

    定义函数有两种方式:

    • 声明式:function f(){}
    • 函数表达式: var f = function(){}

    函数提升是整个函数体提升,变量提升是提升的变量名。

    如上图所示,通过表达式定义的函数提升,报了一个TypeError的错误;是因为预编译期将var关键字提升,也就是说这里的f就是一个普通变量,它的初值被赋为undefined;当代码执行到第11行f();时就相当于是undefined();,所以肯定会报类型错误。

    函数与变量同时提升


    当函数名与变量名同名,且同时提升,以函数为准。
    理由是函数是一等公民,地位高于变量。

    提升不能跨script标签

    开始那道题的答案

    ES6中的变量提升以及暂时性死区

    在 ES6 中以 let 与 const 关键字声明的变量会在作用域头部被初始化,不过这些变量仅允许在实际声明之后使用。在作用域头部与变量实际声明处之间的区域就称为所谓的暂时死区(Temporal Dead Zone),TDZ 能够避免传统的提升引发的潜在问题。

    小结

    以上,就是关于JavaScript变量提升的知识小结。

    相关文章

      网友评论

        本文标题:关于JavaScript变量提升那点事儿

        本文链接:https://www.haomeiwen.com/subject/ynnyrxtx.html