【问题标题】:Using namespace in javascript在 JavaScript 中使用命名空间
【发布时间】:2016-05-19 09:02:38
【问题描述】:

我正在阅读this JavaScript code

我不明白的是,作者为什么这样做:

(function(namespace) {
    //more stuff here
    namespace.Game = Game;
})(window);

namespace.Game = Game; 代替 window.Game = Game; 的目的是什么?

它是否使Game 函数可重用?

【问题讨论】:

  • @ste2425:OP 的 cmets 之一:I'm not confused with IIFE, just that why he assign Game to namespace.Game instead of just window.Game。从该评论来看,我认为这个问题不符合重复的条件。无论如何,我添加了这个问题以消除歧义,因为其他几个人似乎已经将其解释为要求解释使用 IFEE 的意义...

标签: javascript


【解决方案1】:

貌似作者来自C++社区:P,所以他用了变量名“namespace”!!!

本文的作者创建了 IIFE(立即调用函数表达式),因此他/她可以创建私有/隔离范围,他将全局窗口对象作为参数传递,以通过减少范围查找时间来提高性能。(请记住 Javascript 查找属性在本地范围和向上链接到全局范围的方式)。因此在本地范围内访问窗口对象可以减少查找时间。然后他/她用属性“Game”更新了全局对象。

【讨论】:

  • 如果参数名是window,他做window.Game就可以了吗?
  • @HarisZ ,是的,你应该可以。您可以使用简单的代码在浏览器的 javascript 控制台中轻松确认。
【解决方案2】:

作者创建了 IIFE(立即调用函数表达式)并将 window 对象作为参数传递,因此当前函数表达式具有自己的隔离范围,仍显式控制访问全局变量

【讨论】:

  • 我对 IIFE 并不感到困惑,这就是为什么他将 Game 分配给 namespace.Game 而不是 window.Game
  • 好吧,Kyle Simpson 在他的 You Don't Know JS: Scope and Closures 中解释为“这样我们就可以对全局引用和非全局引用有一个清晰的风格划分”。为什么不直接使用window.Game?嗯......因为这不是一种常见的做法,而且在模块代码块中设置自己的变量总是更好
【解决方案3】:

我将在下文中将Game 称为foo

通过这样做,foo 将可以通过全局window 访问,例如window.foo。但是,在哪里分享foo 的决定不应该来自编写foo 的同一个人,而应该来自将foo 集成到他的代码中的那个人。这只是提高互操作性/可重用性的最佳实践。

如果您不这样做,foo 将不会对IIFE 之外的任何人可见。

如果您将foo 直接分配给window,则其他实施方将不得不修改您的代码,而不是更改单个参数。这完全取决于您在代码中真正需要什么样的知识。您真的想知道foo 将在哪里共享,还是只想在某个地方共享?

此外,如果您只是从 IIFE 中访问window,您将访问一个全局变量。请阅读here - “不要污染全局命名空间”

【讨论】:

  • 分配做 windows.Game 而不是 namespace.Game 有什么问题?
【解决方案4】:

这个表达式被称为 IIFE(立即调用的函数表达式)。主要用途是创建一个“范围”。由于只有函数在 javascript 中创建范围。当你想在全球环境中隐藏你的价值观时,你可以使用 IIFE。

(function(namespace) { // begin IIFE
// These values inside can not be accessed from global.
// But we do need a way to access these values, we add all values to 'namespace',
namespace.Game = Game;
// we pass window to this IIFE, so 'namespace == 'window' inside it.
// namespace can be anyword, it is just a parameter.
// since 'window' is value exist in global, all data we appended to it can be access from global via 'window'.
// You can pass any object, or anything, it is just an argument, just like you invoke a function. e.g. if we pass 'Steam'( an object created before), then we can run 'Steam.Game'.
})(window);    // end IIFE
// later we can ,
// window.Game 

【讨论】:

    【解决方案5】:

    要了解IFEE 的意义,请参阅What is the (function() { } )() construct in JavaScript?。基本上,就是尽可能避免使用全局变量。

    那么在这种情况下如何使用namespace 参数呢?好吧,namespace 的值就是window 对象,因为window 对象被传递给self-executing anonymous functionencapsulates 你的代码作为namespace 参数。所以,namespace.Game = window.Game

    使用namespace 参数而不仅仅是直接使用window 对象的一个​​原因是因为namespace 可以是minified,而window 不能...这意味着您可以节省大量字节如果您需要大量引用window 对象。

    使用namespace 变量的另一个原因是,您可能希望您的代码在以后与不存在window 对象的其他环境(如NodeJS)兼容。或者,您可能希望将代码重写为例如。 RequireJS 模块。除了包裹在代码中的匿名函数之外,不在任何地方硬编码 window 对象,这样会容易得多。

    或者您可能只是想将scope 更改为稍后的某个时间点?也许您想在稍后的某个时间点将您的Game 添加到不同的对象?如果您避免在任何地方硬编码 window 对象,除了包裹在您的代码周围的匿名函数,这也会容易得多。

    【讨论】:

    • 这就像给windows对象添加一个属性?缩小是什么意思?做window.Game有什么问题?对我来说也是一样。
    • @Haris Z :直接使用window.Game 没有错。如您提到的代码示例中所示,将其分配给变量会更有效。无论如何,我添加了更多信息。希望对您有所帮助?
    • @JohnSlegers 说这种技术用于minification 好处就像说我们使用汽车是因为它们看起来不错。
    • @M K :更好的缩小是我在仅前端代码中使用这种技术的主要原因。如果您认为这不是正当理由,请详细说明!
    • @JohnSlegers 我正在回复您的评论How exactly does this technique avoid usage of global variables? All it does is just substitute window.Game with namespace.Game, where namespace is a reference to the window object. 但是我现在意识到您的意思是全局变量的消耗,而不是全局变量的污染、泄漏/创建。
    猜你喜欢
    • 2021-09-27
    • 2013-02-13
    • 2012-11-06
    • 1970-01-01
    • 2014-10-17
    • 2018-05-29
    • 2010-12-05
    • 2011-12-02
    • 2011-03-25
    相关资源
    最近更新 更多