显然,ES6 doesn't need namespacing因为每个文件都是一个单独的模块。
但是,如何避免全局名称空间干扰?
例如,Babel仅使用scripts/main.js
替换const
来编译我的var
文件。
var alert = 'This line doesn\'t do anything.'
window.alert(alert)

带有IIFE的命名空间(下面名为ANS
)可防止名称冲突:
const ANS = (function () {
const alert = 'This works'
window.alert(alert + '.')
return {alert: alert + ' too.'}
})()
alert(ANS.alert)

向命名空间ANS
添加属性比将其添加到全局命名空间window
或this
更简洁。并且,IIFE提供了进一步的封装。
那么,不是第二种方式,即用IIFE创建自定义命名空间,比第一种更好吗?如果是这样,在ES2015中有更新/更好的方法吗?为什么Babel不为我做这件事?
答案 0 :(得分:9)
显然,ES6不需要命名空间,因为每个文件都是一个单独的模块。
不完全是。每个模块都有自己的范围,这是正确的,但不是每个文件都是模块。 ES6中的脚本与ES5中的脚本一样,并且在全局范围内执行 在这些脚本中,您仍然需要尽可能多地避免使用全局变量,通常不要声明/分配任何变量或者包装您的"模块"在IEFE中给它一个单独的变量范围。
在ES6中有更新/更好的方法吗?
您可以使用块和词法变量声明(let
,const
,function
):
{
const msg = 'This line doesn\'t do anything.'
window.alert(msg);
}
// msg is not defined here
或者您可以在IEFE中使用箭头功能,这样您就可以使用this
来引用全局对象而无需use .call(this)
):
(() => {
var msg = 'This line doesn\'t do anything.'
window.alert(msg);
})();
但是,如何避免全局命名空间干扰或名称冲突?
在ES6模块中,除了内置对象和全局对象之外,没有任何全局内容。避免修改它们。
当然,您需要注意模块名称之间的冲突 - 如何执行此操作应在模块加载器的解析器机制的文档中进行说明。
答案 1 :(得分:2)
但是,如何防止覆盖模块中的全局变量?
你做不到。与ES5相比,这方面没有任何改变。建议仍然是:避免使用全局变量。
答案 2 :(得分:1)
显然,ES6不需要命名空间,因为每个文件都是 单独的模块。
这是错误的信息。据我所知,只有使用 export
的文件才是ES6模块。如果没有export
,ES6文件只是一个可以访问全局范围的普通脚本,除非它包含在IIFE中或在构建过程中被转换。
修订版(2016年7月12日):显然,我更错误地纠正了错误信息。正如Kyle Simpson clarifies below,"根据当前的规范,文件是ES6模块的原因是环境(节点,浏览器等)选择如何加载它而不是其内容。"
在你不知道JS:ES&超越,Kyle Simpson,a.k.a。@getify,陈述
"模块仍然可以访问窗口和所有"全局"那 悬挂它,只是不作为词汇顶级范围。但是,你真的 如果可能的话,应该远离模块中的全局变量。"
现在回答你的问题。
[我]第二种方式,即使用。创建自定义命名空间 IIFE,比第一个好吗?
这取决于模块运行的环境。例如,在node
中,没有Window
个对象;因此,在该环境中,无需担心您的模块会污染全局命名空间。
另一方面,在浏览器中,Window
是一个全局Web API,您的模块可以访问它。从技术上讲,您的模块附加到Window
的任何内容严格来说都不是全局的;但是,附加到Window
的任何内容都非常接近全局,除了通过Window
own API之外,通常认为修改它是一种不好的做法。< / p>
[H]我应该避免全局名称空间干扰吗?
和
[我]在ES2015中有更新/更好的方法吗?
我不知道在ES6中处理范围的最佳做法是什么。暂时,我会做以下事情:
来源:You Don't Know JS: ES & Beyond 同样推荐:Jason Orendorff的ES6 In Depth: Modules
答案 3 :(得分:0)
通过谷歌搜索同样的问题偶然发现。假设您使用模块加载器(如汇总),请尝试将此行添加到汇总选项中:
format: 'iife'
文档:https://github.com/rollup/rollup/wiki/JavaScript-API#format