import and export 之 (export)

ES6供应了两个关键字import导入和export导出,语法上有些差异。
!important: importexport必需,一直显现在,其各自用法的,顶级局限中。也就是说不能够在if前提中安排importexport; 它们必需放在一切函数以外。

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()函数。用户能够别的手动将barbaz列为定名导入,假如他们想要的话。

你能够设想假如你有许多定名的导出绑定,你模块的用户将是何等乏味。这里有一个通配符导入表单,您能够在单个定名空间对象中导入一切模块的exports,然则没法将通配符导入到顶级绑定。

一样,ES6模块机制被故意设想为阻挠具有大批输出的模块;相对来讲,愿望如许的要领有点难题,作为一种社会工程,它勉励简朴的模块设想,由于这将有利于大/庞杂的模块设想。

我发起你不要夹杂default export定名exports,这将是是不切实际或不须要,特别是假如你有一个大的API和重构零丁的模块。在这类情况下,只需运用一切named exports,并纪录您的模块的用户应当运用import * as ..(定名空间导入)要领在单个定名空间中马上带来全部API。

我们之前提到过,但让我们更细致地回味一下。除了导出表达式值绑定的export default ...外,一切其他导出表单,都正在导出绑定到当地标识符。

    原文作者:Just_do
    原文地址: https://segmentfault.com/a/1190000015615407
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞