• 技术文章 >web前端 >前端问答

    es6 import会变量提升吗

    青灯夜游青灯夜游2023-01-18 19:44:41原创57

    ES6 import会产生变量提升的现象。变量提升是将变量声明提升到它所在作用域的最开始的部分。js要经历编译跟执行阶段,在编译阶段的时候,会搜集所有的变量声明并且提前声明变量,而其他的语句都不会改变他们的顺序,因此,在编译阶段的时候,第一步就已经执行了,而第二部则是在执行阶段执行到该语句的时候才执行。

    本教程操作环境:windows7系统、ECMAScript 6版、Dell G3电脑。

    变量提升

    JavaScript是单线程语言,所以执行肯定是按顺序执行。但是并不是逐行的分析和执行,而是一段一段地分析执行,会先进行编译阶段然后才是执行阶段。在编译阶段阶段,代码真正执行前的几毫秒,会检测到所有的变量和函数声明,所有这些函数和变量声明都被添加到名为Lexical Environment的JavaScript数据结构内的内存中。所以这些变量和函数能在它们真正被声明之前使用。

    先从一个简单的例子来入手:

     a = 2;
     var a;
     console.log(a);

    以上的代码会输出什么,假如这段代码是从上到下执行的话,肯定会输出undefined,然而JavaScript却不是自上而下执行的语言。 这段代码的输出结果是2,意外吗?那么,为什么会这样,这个关键点就在于--变量提升。他会将当前作用域的所有变量的声明,提升到程序的顶部,因此,上面的代码等价于以下代码,这样是不是就能明白一些了?

     var a;
     a = 2;
     console.log(a);

    那么我们再看一个例子:

     console.log(a);
     var a = 2;

    这段代码又会输出什么?输出2吗? 其实这段代码会输出undefined。这又是为什么呢?刚刚说过,JavaScript会将变量的声明提升到顶部,但是赋值语句是不会提升的,对于js来说,var a = 2是分为两步解析的:

    var a;
    a = 2;

    而js只会提升 var a 这句,所以刚刚的语句等价于:

     var a;
     console.log(a);
     a = 2;

    那么,为什么会有变量提升?

    为什么会出现变量提升这个现象呢? 因为js与其他语言一样,都要经历编译跟执行阶段。而js在编译阶段的时候,会搜集所有的变量声明并且提前声明变量,而其他的语句都不会改变他们的顺序,因此,在编译阶段的时候,第一步就已经执行了,而第二部则是在执行阶段执行到该语句的时候才执行。

    ES6的import变量提升

    ES6 import 会产生变量提升的现象。

    比如以下的测试代码,

    // a.js
    console.log('I am a.js...')
    import { foo } from './b.js';
    console.log(foo);
    // b.js
    console.log('I am b.js...')
    export let foo = 1;

    运行a.js,

    // node -r esm a.js 
    I am b.js...
    I am a.js...
    1

    打印的结果是先出现‘I am b.js...’,然后再出现‘I am a.js...’,这就是变量提升的现象。

    这是因为 ES6 在语言标准层面上实现了模块功能,所以当对a.js预编译时发现关键词import后,先去加载b.js,所以先输出‘I am b.js...’。

    整个流程是,

    1.png

    变量提升的产生,其实与变量对象的创建过程有关。

    变量对象创建过程

    变量对象(Variable Object)的创建,依次经历以下几个步骤。

    2.png

    function声明会比var声明优先级更高一点。

    function test() {
      console.log(a);
      console.log(foo());
    
      var a = 1;
      function foo() {
        return 2;
      }
    }
    
    test();

    直接从test()的执行上下文开始理解。

    // 创建过程
    testEC = {
        // 变量对象
        VO: {},
        // 作用域链
        scopeChain: {}
    }
    
    // VO 为 Variable Object 的缩写,即变量对象
    VO = {
        arguments: {...},
        foo: <foo reference>    // 表示foo的地址引用
        a: undefined
    }

    test()执行的结果是,

    // node -r esm demo01.js 
    undefined
    2

    其实,上面的代码demo01.js,变成了这样的执行顺序,

    function test() {
        function foo() {
            return 2;
        }
        var a;
        console.log(a);
        console.log(foo());
        a = 1;
    }
    test();

    【相关推荐:javascript学习教程

    以上就是es6 import会变量提升吗的详细内容,更多请关注php中文网其它相关文章!

    声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn核实处理。
    专题推荐:变量提升 ES6 javascript
    上一篇:es6怎么判断数组里总共有多少项 下一篇:自己动手写 PHP MVC 框架(40节精讲/巨细/新人进阶必看)

    相关文章推荐

    • es6怎么删除数组中的某一项• es5和es6怎么实现数组去重• es6怎么判断字符串中是否有某个字符串• es6怎么判断是否在数组里• ie6能不能兼容es6• es6是基于哪种语言的语法
    1/1

    PHP中文网