ES6 Module之export 解读

已默认读者了解本篇自言自语的context,且对于module有所了解,对于module的相关扩展说明将穿插在内容中(本篇不会提及class),由于是只是export,所以......import请容我忽略

本篇代码运行环境为{"presets": [ "es2015","stage-2" ] }这只是作为参考,且只是运行环境,不推荐在学习ES6时将代码全部转译为ES5,ES6转化后的代码只能告诉你结果,相比较而言,原因或是理由的价值超过结果,学习ES6,不单单要知道代码运行的结果,最重要的目的是,知其所以然,了解一个行为为什么会这么发生,行为的背后又是什么,这才是学习者所需要追寻的

文章参考:
You-Dont-Know-JS
ECMAScript 6 入门
ES6规范15.2.3.2 Static Semantics: BoundNames

首先登场的就是 export , 这是一个主要关键词,基本用法是放置在一个"声明"之前,或一组由{}语法(注意,此处的{}语法与对象无关)包裹的即将被导出的"标识符"之前

//export 放置在"声明"之前
export var a = 1, b = 2, c = 3
export let a = 1
export const a = 1
export let { a } = { a: 1 }
export var foo = function() {}
export function foo() {}

//export 放置在一组"标识符"之前
var a = 1, b = 2
export { a, b }
//等同于
export var a = 1
export var b = 2

以上例子有一个明确的共同点,export 后面没有出现“表达式”。实际上,单独的export 是对变量标识符(指针位置)的绑定,并期许将来会把对应的标识符(指针)导出。

将“变量标识符”导出,这样的描述容易产生混淆,考虑下面的代码

var a = 1
export { a }
a = 3
//等同于
export var a = 1
a = 3

当这个模块被导出后,如果赋值发生,那么已被导出的值也将被更新,无论导出发生在任何阶段。进一步的说,在被导入时的值是无关紧要的。这些绑定是实时的链接,所以唯一重要的是当你访问这个绑定时它当前的值是什么。

  1. 声明
  2. 导出标识符 a,此刻的 a 是指向变量本身的一个引用,或指针,而不是它的值的一个拷贝
  3. 模块内部,a 被重新赋值,已经导出的值也会被自动更新
参考规范15.2.3.2
ExportDeclaration : export VariableStatement
  1. Return the BoundNames of VariableStatement.
ExportDeclaration : export Declaration
  1. Return the BoundNames of Declaration.
可以看到export 的导出是明确的

另外“标识符”一词引用于The above rule means that each ReferencedBindings of ExportClause is treated as an IdentifierReference.主要是词穷,并且因为模块导出与赋值是不同的,在进行导出时,实质上是导出了一个单向绑定的(不允许在导入的一方进行改变)变量的引用,是的,更准确的说应该是对于变量这个容器的引用,模块导出并不关心变量的值。

在进行导出的时候,可以使用别名,关键词 as

var a = 1
export { a as b }
//将 a 重命名为 b

"在一个模块中,使用import命令的时候,用户需要知道所要加载的变量名或函数名,否则无法加载。但是,用户肯定希望快速上手,未必愿意阅读文档,去了解模块有哪些属性和方法。"

"为了给用户提供方便,让他们不用阅读文档就能加载模块,就要用到export default命令,为模块指定默认输出。"

上述两句直接摘自ECMAScript 6 入门,主要是感觉是很恰当的描述,如果加以变动反倒画蛇添足了,当然还不够全面,所以对default进来以下的补充

  1. 每个模块定义只能有一个default,它是唯一的,每个被导出的模块只包含一个default元素,所以export default命令在模块内只被允许使用一次。

  2. 本质上export default就是输出一个叫做default的默认标识符。等同于,将export default 之后的内容以赋值的形式添加到default元素上。

var a = 1
export default a 
//等同于
export default 1
//导出的是那表达式在那一刻的值的绑定,不是 标识符a的绑定(export.default = 表达式)

export default 有许多微妙的细节,令人困扰的(不是结果,而是行为)。请思考下面的代码。

//m2.js
1.
function foo() {}
export default foo
foo = 'change'

2.
export default (function foo() {})
foo = 'change'

3.
function foo() {}
export { foo as default }
foo = 'change'
//由于上文已经描述过,default接近于标识符,所以,可以直接重命名foo作为default导出。

4.
export default function foo() {}
foo = 'change'

//另一模块
import * as all from 'm2.js'
console.log(all)

你的大脑能够清晰的知道每个模块即将会发生的事情吗?如果不能那么请继续阅读,如果能,那么也希望你继续阅读,重温复习这一片段。下面让我复制代码,描述并解释每一模块的行为。

模块1.
function foo() {}
//声明foo
export default foo
//将foo赋值给default元素(注意,此时foo是表达式)
foo = 'change'

//结果
{ default: [Function: foo] }

export default 导出的是那一个函数表达式在那一刻的值的绑定,不是 标识符foo的绑定。换句话说,export default ..接收一个表达式。如果你稍后在你的模块内部赋给foo一个不同的值,这个模块导入将依然表示原本被导出的函数,而不是那个新的值。

规范里定义了export default 表达式的导出相关行为export default AssignmentExpression

ExportDeclaration : export default AssignmentExpression ;
1.Return «"default"».
简单解释下,就是将表达式的值赋予default,然后返回default

模块2.
export default (function foo() {})
将(..)赋值给default 元素(注意,()是表达式)
foo = 'change'
//结果
ReferenceError: foo is not defined
export default !function foo() {}
!等运算符可以包装一个函数使它作为一个表达式返回值

export default (function foo(){}),export default后面的是函数表达式,并不是函数声明定义,所以它对应的规范与模块1相同,导出的ExportedBindings也就是一个«"default"»。

这里之所以报错是因为函数表达式只会返回函数本身作为值,并不会在外部作用域定义同名变量,所以下面的foo = 'change'找不到foo这个定义。

模块3.
function foo() {}
export { foo as default }
foo = 'change'
//结果
{ default: 'change' }

ExportDeclaration : export Declaration
1.Return the BoundNames of Declaration.
行为与 export '标识符‘相同,所以引用的规范相同,唯一需要理解的是default是可以被赋值

模块4.
export default function foo() {}
//一个函数声明出现了!
foo = 'change'
//结果
{ default: 'change' }

function foo..部分是一个函数表达式,但是对于模块内部作用域来说,它被视为一个函数声明,因为名称foo被绑定在模块的顶层作用域

export default 函数声明定义在规范中定义的行为,对应的是export default HoistableDeclaration.
ExportDeclaration : export default HoistableDeclaration
1.Let declarationNames be the BoundNames of HoistableDeclaration.
2.If declarationNames does not include the element "default", append "default" to declarationNames.
3.Return declarationNames.

可以看到按照规范如果将要导出的声明没有包含元素default,那么就进行赋值(规范概念),最后返回的是一个当前绑定的标识符,与前面的表达式时状态不同。所以结果能够看到,导出值被更新了。

原标题为ES6 Module 详解,然后发现自己并没有真正理解Module这部分于是停笔,回去看书了,实际意义上本文是为了总结知识

初学ES6,文章有误请指点,文内部分用词不准确也请谅解,虽然引用了规范,但是并没有能力进行解读,惭愧。

文章参考:
You-Dont-Know-JS
ECMAScript 6 入门
ES6规范15.2.3.2 Static Semantics: BoundNames

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,948评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,371评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,490评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,521评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,627评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,842评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,997评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,741评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,203评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,534评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,673评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,339评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,955评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,770评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,000评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,394评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,562评论 2 349

推荐阅读更多精彩内容

  • 官方中文版原文链接 感谢社区中各位的大力支持,译者再次奉上一点点福利:阿里云产品券,享受所有官网优惠,并抽取幸运大...
    HetfieldJoe阅读 3,655评论 2 27
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,633评论 18 139
  • 以下内容是我在学习和研究ES6时,对ES6的特性、重点和注意事项的提取、精练和总结,可以做为ES6特性的字典;在本...
    科研者阅读 3,120评论 2 9
  • 总是有很多话不去说 总是有很多事不去想 总是认为自己所做的一切都是对的 总是不敢回头面对殷切的暮光 繁华的城市从没...
    择若阅读 460评论 4 1