export

  • export命令用于规定模块的对外接口
export const foo = 'foo'
export function bar(){..}
或者
const foo ='foo'
const bar = ()=>{..}
export {foo,bar as baz}
  • 可以使用as关键字,重命名了对外接口

import

  • 使用export命令定义了模块的对外接口以后,其他 JS 文件就可以通过import命令加载这个模块
  • 可以使用as 关键字重命名接口
  • import命令输入的变量都是只读的,因为它的本质是输入接口。也就是说,不允许在加载模块的脚本里面,改写接口。如果该接口只是一个对象,可以赋值(不推荐)
  • import命令具有提升效果,会提升到整个模块的头部,首先执行。
  • import命令是编译阶段执行的,在代码运行之前。
  • 由于import是静态执行,所以不能使用表达式和变量,这些只有在运行时才能得到结果的语法结构。
  • 如果多次重复执行同一句import语句,那么只会执行一次,而不会执行多次。

export default

用处

使用import命令的时候,用户需要知道所要加载的变量名或函数名,否则无法加载。但是,用户肯定希望快速上手,未必愿意阅读文档,去了解模块有哪些属性和方法。

为了给用户提供方便,让他们不用阅读文档就能加载模块,就要用到export default命令,为模块指定默认输出。

//default.js
export default function(){
return 'foo'
}
//main.js
import foo from './defalut/js'
foo()
//其他模块加载该模块时,import命令可以为该匿名函数指定任意名字。

注: 需要注意的是,这时import命令后面,不使用大括号。 即使export default的函数有函数名,在加载的时候, 视同匿名函数加载

export defalut 与 default区别:

// 第一组
export default function crc32() { // 输出
  // ...
}

import crc32 from 'crc32'; // 输入

// 第二组
export function crc32() { // 输出
  // ...
};

import {crc32} from 'crc32'; // 输入
  • 使用export default定义的接口,加载时不需要用大括号,export定义的则需要用大括号包裹
  • export default命令用于指定模块的默认输出。显然,一个模块只能有一个默认输出,因此export default命令只能使用一次。所以,import命令后面才不用加大括号,因为只可能唯一对应export default命令。
  • 本质上,export default就是输出一个叫做default的变量或方法,然后系统允许你为它取任意名字。
  • 因为export default命令其实只是输出一个叫做default的变量,所以它后面不能跟变量声明语句。

export 与 import 的复合写法

如果在一个模块之中,先输入后输出同一个模块,import语句可以与export语句写在一起。

export { foo, bar } from 'my_module';

// 可以简单理解为
import { foo, bar } from 'my_module';
export { foo, bar };

注: 写成一行以后,foobar实际上并没有被导入当前模块,只是相当于对外转发了这两个接口,导致当前模块不能直接使用foobar

具名接口改为默认接口的写法如下。

export { es6 as default } from './someModule';

// 等同于
import { es6 } from './someModule';
export default es6;

import() 

  • import命令会被 JavaScript 引擎静态分析
  • 如果import命令要取代 Node 的require方法,这就形成了一个障碍。因为require是运行时加载模块,import命令无法取代require的动态加载功能。
//动态加载
const path = './' + fileName;
const myModual = require(path);

ES2020提案: 引入import()函数,支持动态加载模块。

import(specifier)
/*import函数的参数specifier,指定所要加载的模块的位置。import命令能够接受什么参数,import()函数就能接受什么参数,两者区别主要是后者为动态加载。*/
import()返回一个 Promise 对象。

import()函数可以用在任何地方,不仅仅是模块,非模块的脚本也可以使用。它是运行时执行,也就是说,什么时候运行到这一句,就会加载指定的模块。另外,import()函数与所加载的模块没有静态连接关系,这点也是与import语句不相同。import()类似于 Node 的require方法,区别主要是前者是异步加载,后者是同步加载。

使用场合

1.按需加载

button.addEventListener('click', event => {
  import('./dialogBox.js')
  .then(dialogBox => {
    dialogBox.open();
  })
  .catch(error => {
    /* Error handling */
  })
});

2.条件加载

if (condition) {
  import('moduleA').then(...);
} else {
  import('moduleB').then(...);
}

3. 动态的模块路径 import()允许模块路径动态生成。

import(f())
.then(...);

注: import()加载模块成功以后,这个模块会作为一个对象,当作then方法的参数。因此,可以使用对象解构赋值的语法,获取输出接口。


爬。