本来说尝鲜使用下es6的import和export呢,结果以上来就遇到了问题了,发现以原来require的思维(CommonJS)去使用es6的module了。
您能看出问题吗
首先要说的就是,下面的测试走不通报错,但您能看出问题在哪里吗,如果不能,也许需要继续读下去,真正了解下es6的module。
//controller/union.jsexport async function transReqPage(ctx, next) { return await {'hello': 'world'};}//test-import.jsimport unionController from '../controller/union';unionController.transReqPage() .then(function(res) { console.log(res); }) .catch(function(err) { console.log(err); });
错误信息
suntopo@suntopo-X550VX:~/Desktop/workspace/UionPay$ babel-node ./test-import.js/home/suntopo/Desktop/workspace/UionPay/test-import.js:9_union2.default.transReqPage().then(function (res) { ^TypeError: Cannot read property 'transReqPage' of undefined...
export
导出总体上分为两种: 命名导出,默认导出
命名导出
export { name1, name2, …, nameN };export let name1 = …, name2 = …, …, nameN; // also var, constexport function name1(…) { … } // also class, function*
常见的就三种
function test() {console.log('test')}export {test, test as test1}
export function test() {console.log('test');}
export var test = 'test';
常见的错误形式
var test = 'test';export test
function test() {console.log('test');}export test
究其原因:export规定的是对外的接口,必须与内部变量建立一一对应关系,即既要有接口名,又要有变量名,接口名可以显示指定也可以隐式的指定,但无非就是上面说的几种形式,最明显的形式可以这样
export { a as b}
这里明确的指明的接口名b,同是也指明了一一对应的变量a,但是这种形式还是有些繁琐尤其在接口名和变量名相同的时候,于是可以写成这样
export {a}
当变量a变得很简单的时候,这样写也可能会比较繁琐,于是乎又有了简写
export var a=1;
当我们的模块也许只有一个接口的时候,或者说想要模块有一个默认的接口的时候,有可以再次简写--默认导出
默认导出
export default function() {console.log('test')}
实际上解释默认导出时,如果从用户使用import的角度来解释更加清楚,比如用户在使用模块的时候,她必须清楚模块接口的名字才能正确引用,但是这往往给用户带来很大的不便,比如说该模块就一个接口,或该模块有一个默认的接口,我就想拿来就用而已,于是才有了默认导出。
注:一个模块只能有一个默认导出
import
导入和导出总是相对的,既然导出有两种,那么导入也可能会有不同。
import * asname from "module-name"; import { member } from "module-name"; import { member as alias } from "module-name"; import { member1 , member2 } from "module-name"; import { member1 , member2 as alias2 , [...] } from "module-name"; import defaultMember, { member [ , [...] ] } from "module-name"; import defaultMember, * as name from "module-name"; import defaultMember from "module-name"; import "module-name";
命名导入
在导出中我们强调了两个关键字,接口名和变量名,对于导入而言我们关心的只有接口名,只有知道接口名才能正确的调用该接口。
import接受一个对象,里面指定要从其他模块导入的接口名
import {test} from './test'
同样,也可给导入到该模块的接口重命名
import {test as test1} from './test'
但是当需要导入多个接口的时候,一个个写接口可能不现实,所以提供了导入整个模块所有接口的写法
import * as TEST from './test';
默认导入
可以导出默认选项,无论是一个对象,一个函数或一个 class。相对地, 也可以使用 import 默认导出,不用{}, 不用变量名,不用as,导入的就是默认导出的几口
最简单版本,直接导入默认
import test from './test'
混合版
import test, * as test1 from './test';
注意: test1中并不包含test接口,各自独立的,尽管使用了*
那么问题处在哪里呢
首先看下我导出和导入的方式
export async function transReqPageimport unionController from '../controller/union';
我们导入的方式实际上是采用默认导入,但是导出却没有默认导出,所以报找不到方法咯。那么我们该怎么修改呢?首先要看我们的需求,如果我们的模块仅仅只需要导出一个接口,那么在export后面加上default就OK了,但是通常情况下我们需要导出多个接口,所以这里需要我们修改下导入的方式,采用命名导入方式,例如其中一种导入所有的接口
import * as unionController from '../controller/union';
动态绑定
不同于CommonJS的拷贝,es6的模块使用动态绑定,即导入是导出的一个引用,详细内容见