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
- Let declarationNames be the BoundNames of HoistableDeclaration.
- If declarationNames does not include the element "default", append "default" to declarationNames.
- 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 ;
- 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
- 包含f和default的List
- 包含f的List
- 包含default的List
- 包含default的List
ES6规范可以点这里查看 15.2.3.2 Static Semantics: BoundNames
这篇关于javascript - 关于ES6模块加载的一点小疑惑。的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!