export 与 export default


ES6 的模块若要公开名称,可以使用export,必须注意的是,为了表示公开的是名称,必须使用{}包含,就算只有一个名称要公开也是一样,例如:

let a = 10;

export {a};

这样的export称为 Named Export,你不可以这么编写:

let a = 10;

export a;  // SyntaxError: Unexpected token export

相对地,在import时也必须使用{}表示要导入的是名称,就算只有导入一个名称:

import {a} from './foo';

export的是名称,不是被参考的值,因此若名称后来被指定了新的值,另一个模块导入后获取的值也会是新的值,例如,如果从下面这个模块导入了a,那么值会是 20:

let a = 10;
export {a};
a = 20;

你可能会想要从某个模块导入名称之后,在目前的模块再进行公开,例如:

import {a, b} from './foo';
export {a, b};

一个更方便的写法是:

export {a, b} from './foo';

若再度公开名称时必须改名也是可以的:

export {a as x, b as y} from './foo';

如果要公开的是全部的名称,可以使用*

export * from './foo';

如果你要导出一个「值」,可以使用export default,例如:

export default 10;

一个模块只能有一个export default,另一个模块要导入这个值的话,必须指定一个变量,例如:

import a from '.foo';

注意到,这边使用的是a而不是{a}。由于export default导出的是一个值,因此像是底下的范例:

let x = 10;
export default x;
x = 20;

实际上被export default的是x的值 10,因而后续将x设为 20,导入此模块的另一模块,得到的值并不会是 20,一个模块可以同时有多个export与一个export default

export default可以让模块的客户端,在不知道模块中导出了哪个名称的情况下,就能自定义名称取用模块功能,例如,export default一个工厂函数,之后使用该工厂函数来取用模块名称:

// 模块功能实现
...

// 提供工厂函数
function factory(...) {
    ....
}

export default factory;

另一模块可以自定义工厂函数名称,例如:

import XD from './foo';

XD('id').html('<b>这只是个示范</b>');

也许你会想到,export default一个对象,让该对象作为命名空间:

export default {
    f1 : function(...) {...},
    f2 : function(...) {...},
    ...
};

虽然客户端最后可以像过去那种,以单一对象作为命名空间的方式来使用此模块的功能,然而,ES6 并不鼓励使用这种方式,理由是被import的对象无法静态分析,在必要的时候进行最佳化之类。

export default的本质上,其实是使用default作为公开的名称,而default的值就是export default后指定的值,因此,也可以使用底下方式来import

import {default as a} from './foo';

因此,如果你导入了某个模块,想要直接导出该模块的default,可以如下:

export {default} from './math';

如果编写了底下的程序:

import a from './foo';
export {a as x};

那么可以直接改为:

export {default as x} from './foo';

如果编写了底下的程序:

import {a} from './foo';
export default {a};

那么可以改为:

export {a as default} from './foo';




展开阅读全文