在ES6中使用IIFE命名?

时间:2015-09-23 18:11:15

标签: namespaces global-variables ecmascript-6 babeljs iife

显然,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添加属性比将其添加到全局命名空间windowthis更简洁。并且,IIFE提供了进一步的封装。

那么,不是第二种方式,即用IIFE创建自定义命名空间,比第一种更好吗?如果是这样,在ES2015中有更新/更好的方法吗?为什么Babel不为我做这件事?

4 个答案:

答案 0 :(得分:9)

  

显然,ES6不需要命名空间,因为每个文件都是一个单独的模块。

不完全是。每个模块都有自己的范围,这是正确的,但不是每个文件都是模块。 ES6中的脚本与ES5中的脚本一样,并且在全局范围内执行 在这些脚本中,您仍然需要尽可能多地避免使用全局变量,通常不要声明/分配任何变量或者包装您的"模块"在IEFE中给它一个单独的变量范围。

  

在ES6中有更新/更好的方法吗?

您可以使用块和词法变量声明(letconstfunction):

{
    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中处理范围的最佳做法是什么。暂时,我会做以下事情:

  • 如果文件是一个模块,它的顶级范围就是文件本身,所以我不关心全局范围。
  • 如果文件不是模块,我将其包装在IIFE中。

来源:You Don't Know JS: ES & Beyond 同样推荐:Jason Orendorff的ES6 In Depth: Modules

答案 3 :(得分:0)

通过谷歌搜索同样的问题偶然发现。假设您使用模块加载器(如汇总),请尝试将此行添加到汇总选项中:

format: 'iife'

Src:https://github.com/samccone/The-cost-of-transpiling-es2015-in-2016/blob/master/rollup-plugin-babel/rollup.config.js#L9

文档:https://github.com/rollup/rollup/wiki/JavaScript-API#format