Skip to content

参考此处为语雀卡片,点击链接查看

深入理解 ES6 模块机制

1、es6模块特性

  1. ********
  2. ****

特性1:输出值的引用

也就是说,在commonjs中,在不同的模块中引入同一个值,是不会相互影响的。而在es6中,是会相互影响的。

javascript
// a.js
import { foo } from './b';
console.log(foo);
setTimeout(() => {
  console.log(foo);
  import('./b').then(({ foo }) => {
    console.log(foo);
  });
}, 1000);

// b.js
export let foo = 1;
setTimeout(() => {
  foo = 2;
}, 500);
// 执行:babel-node a.js
// 执行结果:
// 1
// 2
// 2

特性2:静态编译

********

特性3:模块不会重复执行

javascript
// a.js
import './b';
import './b';

// b.js
console.log('只会执行一次');

// 执行结果:
// 只会执行一次

特性4:循环依赖

javascript
// a.js
console.log('a starting')
import {foo} from './b';
console.log('in b, foo:', foo);
export const bar = 2;
console.log('a done');

// b.js
console.log('b starting');
import {bar} from './a';
export const foo = 'foo';
console.log('in a, bar:', bar);
setTimeout(() => {
  console.log('in a, setTimeout bar:', bar);
})
console.log('b done');

// babel-node a.js
// 执行结果:
// b starting
// in a, bar: undefined
// b done
// a starting
// in b, foo: foo
// a done
// in a, setTimeout bar: 2

特性5:动态import

javascript
if(some condition) {
  import a from './a';
}else {
  import b from './b';
}

// or 
import a from (str + 'b');
`****```
  1. ``
  2. ``
  3. <font style="color:rgb(18, 18, 18);">import() </font>
javascript
// a.js
const str = './b';
const flag = true;
if(flag) {
  import('./b').then(({foo}) => {
    console.log(foo);
  })
}
import(str).then(({foo}) => {
  console.log(foo);
})

// b.js
export const foo = 'foo';

// babel-node a.js
// 执行结果
// foo
// foo

2、模块常见用法

export

export 导出方式有两种,命名导出默认导出

  • 命名导出还是默认导出都是导出模块中内容的一种方式,可以混合使用。
  • 个人理解:默认导出其实是导出了default别名变量。
  • 一个模块只能有一个默认导出
  • 不同的导出方式也对应了不同的导入方式
javascript
// 命名行内导出
export const baz = 'baz';
export const foo = 'foo', bar = 'bar';
export function foo() {}
export function* foo() {}
export class Foo {}
// 命名子句导出
export { foo };
export { foo, bar };
export { foo as myFoo, bar };
// 默认导出
export default 'foo';
export default 123;
export default /[a-z]*/;
export default { foo: 'foo' };
export { foo, bar as default };
export default foo
export default function() {}
export default function foo() {}
export default function*() {}
export default class {}

import

  • 导入对模块而言是只读的,相当于const 变量
  • import导入的值是无法直接修改的,但可以修改导入对象的属性。
javascript
import foo, * as Foo './foo.js';
foo = 'foo'; // 错误
Foo.foo = 'foo'; // 错误
foo.bar = 'bar'; // 允许
  • 对应不同的导出方式,需要使用不同的导入方式:
javascript
// export.js
const foo = 'foo', bar = 'bar', baz = 'baz';
export { foo, bar, baz }
export default foo


// import .js
import * as Foo from './foo.js'; // 导入命名导出内容
import { foo, bar, baz as myBaz } from './foo.js';  // 导入命名导出内
// 导入默认导出的内容
import { default as foo } from './foo.js';//导入默认导出,与下边等效
import foo from './foo.js';//导入默认导出,与上边边等效
  • 如果模块同时使用了命名导出和默认导出,可以这样来在import中同时导入
javascript
import foo, { bar, baz } from './foo.js';
import { default as foo, bar, baz } from './foo.js';
import foo, * as Foo from './foo.js';

模块转移导出

javascript
// 导出foo.js所有命名导出
export * from './foo.js';
// 将foo.js中默认导出修改为命名导出
export {default as foo} from './foo.js'

在组件库或函数库中,我们经常能看到模块转移导出,将需要导出到外部的内容有一个统一的出口,这时要注意导出名称是否会重名等问题