• ES6 入门教程 24 Module 的语法 24.4 import 命令 & 24.5 模块的整体加载


    ES6 入门教程

    ECMAScript 6 入门

    作者:阮一峰

    本文仅用于学习记录,不存在任何商业用途,如侵删

    24 Module 的语法

    24.4 import 命令

    使用export命令定义了模块的对外接口以后,其他 JS 文件就可以通过import命令加载这个模块。

    // main.js
    import { firstName, lastName, year } from './profile.js';
    
    function setName(element) {
      element.textContent = firstName + ' ' + lastName;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    上面代码的import命令,用于加载profile.js文件,并从中输入变量。import命令接受一对大括号,里面指定要从其他模块导入的变量名。

    大括号里面的变量名,必须与被导入模块(profile.js)对外接口的名称相同。

    如果想为输入的变量重新取一个名字,import命令要使用as关键字,将输入的变量重命名。

    import { lastName as surname } from './profile.js';
    
    • 1

    import命令输入的变量都是只读的,因为它的本质是输入接口。

    也就是说,不允许在加载模块的脚本里面,改写接口。

    import {a} from './xxx.js'
    
    a = {}; // Syntax Error : 'a' is read-only;
    
    • 1
    • 2
    • 3

    上面代码中,脚本加载了变量a,对其重新赋值就会报错,因为a是一个只读的接口。但是,如果a是一个对象,改写a的属性是允许的。

    import {a} from './xxx.js'
    
    a.foo = 'hello'; // 合法操作
    
    • 1
    • 2
    • 3

    上面代码中,a的属性可以成功改写,并且其他模块也可以读到改写后的值。

    不过,这种写法很难查错,建议凡是输入的变量,都当作完全只读,不要轻易改变它的属性。

    import后面的from指定模块文件的位置,可以是相对路径,也可以是绝对路径。如果不带有路径,只是一个模块名,那么必须有配置文件,告诉 JavaScript 引擎该模块的位置。

    import { myMethod } from 'util';
    
    • 1

    上面代码中,util是模块文件名,由于不带有路径,必须通过配置,告诉引擎怎么取到这个模块。

    注意,import命令具有提升效果,会提升到整个模块的头部,首先执行。

    foo();
    
    import { foo } from 'my_module';
    
    • 1
    • 2
    • 3

    上面的代码不会报错,因为import的执行早于foo的调用。

    这种行为的本质是,import命令是编译阶段执行的,在代码运行之前。

    由于import是静态执行,所以不能使用表达式和变量,这些只有在运行时才能得到结果的语法结构

    // 报错
    import { 'f' + 'oo' } from 'my_module';
    
    // 报错
    let module = 'my_module';
    import { foo } from module;
    
    // 报错
    if (x === 1) {
      import { foo } from 'module1';
    } else {
      import { foo } from 'module2';
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    上面三种写法都会报错,因为它们用到了表达式、变量和if结构。在静态分析阶段,这些语法都是没法得到值的。

    最后,import语句会执行所加载的模块,因此可以有下面的写法。

    import 'lodash';
    
    • 1

    上面代码仅仅执行lodash模块,但是不输入任何值。

    如果多次重复执行同一句import语句,那么只会执行一次,而不会执行多次。

    import 'lodash';
    import 'lodash';
    
    • 1
    • 2

    上面代码加载了两次lodash,但是只会执行一次。

    import { foo } from 'my_module';
    import { bar } from 'my_module';
    
    // 等同于
    import { foo, bar } from 'my_module';
    
    • 1
    • 2
    • 3
    • 4
    • 5

    上面代码中,虽然foobar在两个语句中加载,但是它们对应的是同一个my_module模块。也就是说,import语句是 Singleton 模式。

    目前阶段,通过 Babel 转码,CommonJS 模块的require命令和 ES6 模块的import命令,可以写在同一个模块里面,但是最好不要这样做。因为import在静态解析阶段执行,所以它是一个模块之中最早执行的。下面的代码可能不会得到预期结果。

    require('core-js/modules/es6.symbol');
    require('core-js/modules/es6.promise');
    import React from 'React';
    
    • 1
    • 2
    • 3
    24.5 模块的整体加载

    除了指定加载某个输出值,还可以使用整体加载,即用星号(*)指定一个对象,所有输出值都加载在这个对象上面。

    下面是一个circle.js文件,它输出两个方法areacircumference

    // circle.js
    
    export function area(radius) {
      return Math.PI * radius * radius;
    }
    
    export function circumference(radius) {
      return 2 * Math.PI * radius;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    现在,加载这个模块。

    // main.js
    
    import { area, circumference } from './circle';
    
    console.log('圆面积:' + area(4));
    console.log('圆周长:' + circumference(14));
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    上面写法是逐一指定要加载的方法,整体加载的写法如下。

    import * as circle from './circle';
    
    console.log('圆面积:' + circle.area(4));
    console.log('圆周长:' + circle.circumference(14));
    
    • 1
    • 2
    • 3
    • 4

    注意,模块整体加载所在的那个对象(上例是circle),应该是可以静态分析的,所以不允许运行时改变。下面的写法都是不允许的。

    import * as circle from './circle';
    
    // 下面两行都是不允许的
    circle.foo = 'hello';
    circle.area = function () {};
    
    • 1
    • 2
    • 3
    • 4
    • 5
  • 相关阅读:
    自编码器AE全方位探析:构建、训练、推理与多平台部署
    制造业数字化转型的实质
    SpringBoot+LayUI+MybatisPlus 前后端分离 实现数据表格下拉框功能
    代码随想录算法训练营 动态规划part06
    Redis 的网络框架是实现了 Reactor 模型吗?
    【大麦小米学量化】什么是量化交易?哪些人适合做量化交易?
    260. 只出现一次的数字 III
    golang设计模式——状态模式
    Python源码剖析1-整数对象PyIntObject
    4.1.9-映射应用程序体系结构
  • 原文地址:https://blog.csdn.net/weixin_44226181/article/details/128010922