javascript - 关于ES6模块加载的一点小疑惑。

查看:136
本文介绍了javascript - 关于ES6模块加载的一点小疑惑。的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

问 题

xx.js
1.
export default function f() { }
f = 'change'
// { default: change }

2.
function f() { }
export { f as default }
f = 'change'
// { default: change }

3.
function fo() { }
export default fo
fo = 'is not'
// { default: [Function: fo] }

4.
export default (function foo() {})
foo = 'is not'
// 抛出 defined 错误

//是作为运行结果,由另一模块为
import * as o from 'xx.js'
console.log(o)

早上闲来无事看看es6模块加载,自己写了上面几个例子,2,3,4都能够自圆其说,但是并不理解1,为什么会被改变。

解决方案

你这些写法都是不同的,所以他们导出的绑定对象也不同,由于分别对应ES6规范里的不同章节,我给你分别说一下。

第一个写法是直接export default 函数声明定义,对应的是export default HoistableDeclaration,它的ExportedBindings是BoundNames,按照规范它的BoundNames是这么获取的:

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.

也就是一个包含了原有绑定名的List。
所以你第一个export default,导出名里有两个,其中一个有f,当你在原来模块改变f的时候就会影响到导出的变量。


第二个export {f as default},表面上看是和第一个等效,但它对应的规范是export ExportClause,其中ExportClause在这里是{ ExportsList },ExportsList在这里是ExportSpecifier,ExportSpecifier在这里是IdentifierName as IdentifierName。

它的ExportedBindings规范里是这么写的:

Return a List containing the StringValue of the first IdentifierName.

这里的first IdentifierName就是你的f,所以导出的Binding List里包含了f这个名字,这样就会让你在原有模块下改变f就会影响到导出的变量。


第三个export default fo ,这里的fo事实上不是函数声明定义,它对应的规范是export default AssignmentExpression,和第一个一样,它的ExportedBindings是BoundNames,但是按照规范它的BoundNames是这么获取的:

ExportDeclaration : export default AssignmentExpression ;

  1. Return «"default"».

可以看到这里的BoundNames只返回了一个«"default"»,没有原来的fo什么的,所以你在原模块里不管怎么改变fo,都和导出的变量无关了。

其实和这个类似:
export let default1 = foo
这个指定后,你改变foo=3,不会影响到default1的。
当然这个是举例,实际上这个规范和export default是不同条数的。


第四个export default (function f(){}),export default后面的是函数表达式,并不是函数声明定义,所以它的规范和第三个一样的,导出的ExportedBindings也就是一个«"default"»。
这里之所以报错是因为函数表达式只会返回函数本身作为值,并不会在外部作用域定义同名变量,所以下面的foo = 'is not'会找不到f这个定义。
类似于

var a = function xxx(){}
typeof xxx // undefined


小结一下你的四个写法ExportedBindings

  1. 包含f和default的List
  2. 包含f的List
  3. 包含default的List
  4. 包含default的List

ES6规范可以点这里查看 15.2.3.2 Static Semantics: BoundNames

这篇关于javascript - 关于ES6模块加载的一点小疑惑。的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆