CommonJS模块与ES6模块相互加载

本文章学习于阮一峰老师的《ES6标准入门》

1. import 命令加载CommonJS模块

Node采用CommonJS模块格式,模块的输出都定义在module.exports属性上面。在 Node环境中,使用import命令加载CommonJS模块,Node 会自动将module.exports属性当作模块的默认输出,即等同于export default。
1.module.exports输出是一个对象,下面是一个CommonJS模块。

// a.js
module.exports ={
foo: 'hello',
bar: 'world'
}
//等同于
export default {
foo: 'hello',
bar: 'world'
;

import命令加载上面的模块,module.exports会被视为默认输出。

//写法一
import baz from ' ./a';
// baz = {foo: 'hello', bar: 'world'};
//写法二
import {default as baz} from ' ./a';
// baz = {foo: 'hello', bar: 'world'};

如果采用整体输入的写法(import * as xxx from someModule), default 会取代module.exports作为输入的接口。

import * as baz from './a';
//baz={
//get default() (return module.exports;},
//get foo() {return this.default. foo} . bind (baz),
//get bar() {return this . default . bar} .bind(baz)
// }

上面的代码中,this.default取代了module.exports。需要注意的是,Node 会自动为baz添加default属性,通过baz.default获取module.exports。

2.module.exports是一个基本数据类型

// b.js
module.exports = null;
// es.js
import foo from ' ./b';
// foo = null;
import * as bar from './b';
// bar = {default:null};


上面的代码中,es.js采用第二种写法时,要通过bar.default这样的写法才能获取module. exports。
3.module.exports是一个函数。

// c.js
module.exports = function twol() {
  return 2;
}
// es.js
import foo from './c';
foo(); // 2
import * as bar from
bar.default(); // 2
bar(); // throws,bar is not a function

上面代码中bar 是一个对象,不能当作函数调用,只能通过bar .default调用。CommonJS模块的输出缓存机制在ES6加载方式下依然有效。

// foo.js
module.exports = 123;
setTimeout(_ => module.exports = null) ;

上面的代码中,对于加载foo.js的脚本,module.exports将一直是123,而不会变成null。
由于ES6模块是编译时确定输出接口,CommonJS 模块是运行时确定输出接口,所以采用import命令加载CommonJS模块时,不允许采用下面的写法。

import {readfile} from 'fs';

上面的写法不正确,因为fs是CommonJS格式,只有在运行时才能确定readfile接口,而import命令要求编译时就确定这个接口。解决方法就是改为整体输入。

import * as express from 'express';
const app = express.default();
import express from 'express';
const app = express();


2. require 命令加载ES6模块

采用require命令加载ES6模块时,ES6模块的所有输出接口都会成为输入对象的属性。

// es.js
let foo = {bar: 'my-default'};
export default foo;
foo = null;
// cjs.js
const es_namespace = require('./es');
console.log (es_namespace.default) ;
// {bar: 'my-default'}

上面的代码中,default 接口变成了es_namespace.default属性。另外,由于存在缓存机制,es.js对foo的重新赋值没有在模块外部反映出来。
下面是另一个例子。

// es.js
export function f() { };
export class C {} ;
// cjs.js
const es_namespace = require('./es') ;
// es_namespace = {
// get foo() {return foo; }
// get bar() {return foo; }
// get f() {return f; }
// get c() {return ci }
// }


 

你可能感兴趣的:(前端模块化)