import and export 之 (export)

2018-07-12 admin

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 ...外,所有其他导出表单,都正在导出绑定到本地标识符。

原文链接:https://segmentfault.com/a/1190000015615407

本站文章除注明转载外,均为本站原创或编译。欢迎任何形式的转载,但请务必注明出处。

转载请注明:文章转载自 JavaScript中文网 [https://www.javascriptcn.com]

本文地址:https://www.javascriptcn.com/read-35862.html

文章标题:import and export 之 (export)

相关文章
JS教程之基础
javascript教程之什么是 JavaScript? JavaScript 被设计用来向 HTML 页面添加交互行为。JavaScript 是一种脚本语言(脚本语言是一种轻量级的编程语言)。JavaScript 由数行可执行计算机代码组...
2015-11-12
Ajax教程之Ajax介绍
Ajax 由 HTML、JavaScript™ 技术、DHTML 和 DOM 组成,这一杰出的方法可以将笨拙的 Web 界面转化成交互性的 Ajax 应用程序。本文的作者是一位 Ajax 专家,他演示了这些技术如何协同工作 —— 从总体概述...
2015-11-12
bootstrap table之通用方法( 时间控件,导出,动态下拉框, 表单验证 ,选中与获取信息)代码分享
1.bootstrap-table 单击单行选中 $('#gzrwTable').on('click-row.bs.table', function(e, row, $element) { $(&#x...
2017-02-17
数据格式之战:JSON vs XML
在比较JSON和XML之前,我们先来上一堂关于数据格式的简要历史(更准确的说,是关于XML的始祖): 早在1970年,IBM开发了一种叫Generalized Markup Language的标记语言,简称GML,它主要是为脚本语言定义的一...
2016-01-13
JavaScript深入之类数组对象与
类数组对象 所谓的类数组对象: 拥有一个 length 属性和若干索引属性的对象 举个例子: var array = ['name', 'age', 'sex']; var ...
2017-05-27
javascript数据结构与算法之检索算法
查找数据有2种方式,顺序查找和二分查找。顺序查找适用于元素随机排列的列表。二分查找适用于元素已排序的列表。二分查找效率更高,但是必须是已经排好序的列表元素集合。 一:顺序查找 顺序查找是从列表的第一个元素开始对列表元素逐个进行判断,直到找到...
2017-03-22
Vue.js原理分析之observer模块详解
介绍 observer是Vue核心中最重要的一个模块(个人认为),能够实现视图与数据的响应式更新,底层全凭observer的支持。 **注意:**本文是针对Vue@2.1.8进行分析 observer模块在Vue项目中的代码位置是src/c...
2017-03-16
HTML5之WebSocket入门3 -通信模型socket.io
socket.io为什么会诞生呢?请看下面文字说明。 为什么需要socket.io? node.js提供了高效的服务端运行环境,但是由于浏览器端对HTML5的支持不一,为了兼容所有浏览器,提供卓越的实时的用户体验,并且为程序员提供客户端与服...
2017-03-29
文字垂直滚动之javascript代码
在大型的网站新闻公告和友情链接等领域经常有这种文字或图片垂直滚动的效果,下面就介绍一下文字垂直滚动的javascript代码。 javascript代码如下: <!DOCTYPE html> <html> <h...
2017-03-27
JS中处理时间之setUTCMinutes()方法的使用
javascript Date.setUTCMinutes()方法按照通用时间设置分钟为一个指定日期。 语法 Date.setUTCMinutes(minutesValue[, secondsValue[, msValue]]) 注:括号...
2017-03-24
回到顶部