ES6供应了两个关键字import
导入和export
导出,语法上有些差异。!important:
import
和export
必需,一直显现在,其各自用法的,顶级局限中。也就是说不能够在if
前提中安排import
或export
; 它们必需放在一切块
和函数
以外。
exporting
API Members 导出API成员
export
关键字要么放在声明之前
,要么作为运算符
(排序)运用要export
的特定绑定列表
。
export function foo() {
// ..
}
export var awesome = 42;
var bar = [1,2,3];
export { bar };
雷同的表达exports
的要领:
function foo() {
// ..
}
var awesome = 42;
var bar = [1,2,3];
export { foo, awesome, bar };
这些都称为 定名导出( named export)
,由于您实际上导出变量/函数/等
的称号绑定
。
任何你不标记export
,会在模块的局限内坚持private
。 也就是说,只管var bar = ..
看起来像是在顶级全局局限
声明,顶级局限
实际上是模块
自身; 模块中没有全局局限
。
注重:模块依然能够接见window
和一切的globals
,挂起它,只是不是作为辞汇顶级局限。 然则,你真的应当阔别全局模块,假如能够的话。
您还能够在定名导出时期对模块成员举行“重定名”(也称为别号):
function foo() { .. }
export { foo as bar };
导入此模块时,只要bar
成员称号可用于导入; foo
坚持隐藏在模块内。
模块导出不仅仅是值或援用的一般赋值,由于您习惯于=
赋值运算符。 实际上,当你导出一些东西,你正在导出一个绑定(有点像一个指针)到谁人东西(变量等)。
在模块中,假如变动已导出绑定的变量的值,纵然已导入(拜见下一部份),导入的绑定也将剖析为当前(更新)的值。
试想一下:
var awesome = 42;
export { awesome };
// later
awesome = 100;
导入此模块时,不管是在awesome = 100
设置之前照样今后,一旦分派已发作,导入的绑定将剖析为值100
,而不是42
。
这是由于绑定本质上是对awesome
变量自身的援用或指针,而不是其值的副本。JS引入了ES6模块绑定,这是一个大多数亘古未有的观点。
虽然您能够在模块的定义中清楚地屡次运用export
,但ES6
相对偏好模块,具有单个导出的要领,这称为default export
。用TC39
委员会的一些成员的话来讲,假如你遵照这类情势,你就会被“简朴的import语法”
所嘉奖,而假如你不这么做,则反过来被更冗杂的语法来“责罚”。
默许导出
将特定导出的绑定设置为导入模块时的默许值。绑定的称号字面上是默许的。正如你将在背面看到的,当导入模块绑定时,你也能够重定名它们,就像你一般运用默许导出一样。
每一个模块定义只能有一个默许值。假如模块具有默许导出
,您将看到导入语法怎样更简约。
关于默许导出
语法有一个玄妙的细微差异,您应当密切注重。比较这两个片断:
function foo(..) {
// ..
}
export default foo;
and
function foo(..) {
// ..
}
export { foo as default };
在第一个片断中,您正在导出一个绑定到此时的函数表达式值,而不是标识符foo
。 换句话说,导出export default ..
采纳一个表达式。 假如今后将foo
分派给模块中的其他值,则模块导入仍会显现最初导出的函数,而不是新值。
趁便说一下,第一个片断也能够写成:
export default function foo(..) {
// ..
}
正告:虽然这里function foo..
在技术上,是一个函数表达式,为了模块的内部局限的目标,它被视为一个函数声明,由于foo
称号绑定在模块的顶级作用域 称为“提拔”)。 出口默许类Foo
也是云云。然则,虽然你能够做到export var foo = ..,
但你现在不能做到export default var foo = ..(或let或const)
,在一个使人懊丧的不一致的情况下。 在撰写本文时,为了一致性,已议论了在ES6今后很快增添这类才能。
function foo(..) {
// ..
}
export { foo as default };
在此版本的模块导出中,默许导出绑定实际上是foo
标识符而不是它的值
,所以您取得前面形貌的绑定行动(即,假如您今后变动foo
的值,你在import
端看到的值也将更新)。
在默许导出语法中要异常警惕这个玄妙的题目,特别是假如你的逻辑须要更新导出值。 假如你从来没有设想更新默许导出的值,export default ..
是很好的。 假如您设想更新值,则必需运用export {.. as default}
。 不管哪一种体式格局,确保批评你的代码怎样来诠释你的企图!
由于每一个模块只能有一个默许值,所以您能够会试图运用一个对象的默许导出,来设想您的模块,个中包括一切的API
要领,比方:
export default {
foo() { .. },
bar() { .. },
..
};
这类情势,好像很密切地,映射了许多开发人员,已构建了,他们的ES6之前的模块,所以,它好像是,一个天然的要领。 不幸的是,它存在一些瑕玷,并正式地不勉励如许做。
特别是,JS引擎,不能静态剖析一般对象的内容,这意味着,它不能对静态导入机能,做一些优化。 每一个成员零丁和显式导出的长处是,引擎能够举行静态剖析和优化。
假如你的API,已有多个成员,好像这些准绳 – 每一个模块一个默许导出,一切API成员名为exports – 存在争执,不是吗? 然则您能够有一个默许导出以及其他定名导出; 它们不是互相排挤的。
因而,替换掉当前的(不发起的)情势:
export default function foo() { .. }
foo.bar = function() { .. };
foo.baz = function() { .. };
you can do that
export default function foo() { .. }
export function bar() { .. }
export function baz() { .. }
注重:在前面的代码段中,我运用称号foo
作为默许函数的标签。 但是,称号foo
,为了导出的目标被疏忽 – default
实际上是导出的称号。 当您导入此默许绑定时,您能够为其指定任何所需的称号,以下一部份中所示。
function foo() { .. }
function bar() { .. }
function baz() { .. }
export { foo as default, bar, baz, .. };
当我们短时间掩盖import
时,夹杂default
和定名exports
的影响将越发清楚。但实质上它意味着最简约的默许import
情势,将只检索foo()
函数。用户能够别的手动将bar
和baz
列为定名导入,假如他们想要的话。
你能够设想假如你有许多定名的导出绑定,你模块的用户将是何等乏味。这里有一个通配符导入表单,您能够在单个定名空间对象中导入一切模块的exports
,然则没法将通配符导入到顶级绑定。
一样,ES6模块机制被故意设想为阻挠具有大批输出的模块;相对来讲,愿望如许的要领有点难题,作为一种社会工程,它勉励简朴的模块设想,由于这将有利于大/庞杂的模块设想。
我发起你不要夹杂default export
与定名exports
,这将是是不切实际或不须要,特别是假如你有一个大的API和重构零丁的模块。在这类情况下,只需运用一切named exports,并纪录您的模块的用户应当运用import * as ..
(定名空间导入)要领在单个定名空间中马上带来全部API。
我们之前提到过,但让我们更细致地回味一下。除了导出表达式值绑定的export default ...
外,一切其他导出表单,都正在导出绑定到当地标识符。