需要有关摆脱全局变量的建议/帮助

时间:2015-04-19 16:01:34

标签: javascript variables architecture global

是的,这是关于全局变量的另一个主题。我对他们进行了相当多的搜索。但是大部分主题都是关于为什么不使用全局变量,我确信我不应该这样做,我更想知道如何不使用它们,而且我仍然不确定

我正在研究一个项目,它可以创造奇迹,但我目前正在使用大约50个全局变量,而且这个数字还在不断增加。现在我已经在多个.js文件中拆分了。像load_chunks.js,load_images.js,render_map.js,player_actions.js,input.js一样,根据它们的用途传播函数。我已将所有全局变量放在settings.js。

目前我出于以下原因使用这些全局变量:
1.基于一些其他全局变量进行计算,这些变量在加载后不会发生太大变化或根本没有变化。通过这样做一次,并将其存储在全局变量中,我不再需要再次重复计算。如果我没有将它存储在(全局)变量中,Javascript必须每秒进行多次计算,在某些情况下甚至高达每秒几千次。
2.当许多函数需要全局变量时。就像那个世界变量一样,我用它来保存世界外观的数据。该变量是一个多维数组。世界[y] [x]例如。 Load_chunks.js向此变量添加更多数据,或者如果移动太远则删除数据。 render_map.js中也需要此变量来创建地图,并且在player_action.js中也需要此变量,以查看您是否可以踩到该特定位置。
3.设置;所以变量中的数字保持不变,除非我在脚本中更改它们。经过漫长的搜索并思考数字是什么后,我不是通过我的脚本,手动更改数字,而是将该数字放在1个变量中,并在我的脚本中多次调用该变量。在某些情况下,这些变量也需要在其他地方使用。

另外我想提一下我不会使用类,也许因为这个原因我从来没有使用过全局变量......?

那么如何摆脱我的全局变量,或者我不应该这样做? 我希望你能告诉我或为我写一个我应该怎么做的脚本示例(或链接)。这是我学习的最快方式。

3 个答案:

答案 0 :(得分:4)

  

我确信我不应该,我更想知道如何不使用它们,而且我仍然不确定。

load_chunks.js, load_images.js, render_map.js, player_actions.js, input.js,强烈暗示程序实现,即你的架构可能有几个功能部分,你可以在这些函数之间传递数据。这就是你的全局变量的来源。

  

那么如何摆脱我的全局变量(...)

要更改它,您需要使用基于对象或组件的方法构建系统,即:

  • 按问题域中的对象封装数据+各自的功能,例如:有一个World对象,其中包含AvatarBuildingsAirborne个对象等(或者您的项目所涉及的任何内容)。

  • 将问题域的逻辑与视图逻辑分开(例如使用MVC architecture

  • 然后您的项目通过在它们之间交换消息来组织视图和模型对象之间的交互。

为了促进这一点,我建议使用这些精美的框架,或者适合您的运行时环境的等价物:

  • requirejs - 将模块封装到全局管理的组件中
  • backbonejs - 拥有一个高效,经过验证的模型/视图,类/对象模型(实际构建用于REST风格的后端,但这不是一个严格的要求)

代码结构

通常,我构建我的应用程序,使每个对象组件/模块都有一个.js文件。这个意义上的模块包含类定义和相应的集合。这些模块由requirejs管理,类定义使用backbonejs完成。

  

我希望你能告诉我或为我写一个脚本示例

/* define a class e.g. in someclass.js */
define(['backbone'], function($B) {
    var SomeClass = $B.Model.extend({
       // all instance variables, methods etc. follow
       someVar : value,
       someMethod : function() { ... }, 
    });
    return SomeClass;
});

/* use the class, e.g. in app.js */
require(['someclass'], function(SomeClass) {
   var instance = new SomeClass({ initial model attributes });
   var value = instance.get('attribute');
   instance.someMethod();
   ...
});

答案 1 :(得分:3)

将变量放入函数关闭

消除全局的一种常见方法是将is放在函数闭包中:

(function() {
     var declareYourFormerGlobalHere = 0;

     // put all code that uses the variable inside this closure
     // the variable persists for this code to use, but is not actually global
})();

以下是一些使用示例:

// example keeping track of a running count and a cached DOM element
(function() {
    var cntr = 0, obj = document.getElementById("test");
    setInterval(function() {
        ++cntr;
        if (obj.value < cntr) {
            // do something
        } else {
            // do something else
        }
    }, 1000);
})();

// example keeping track of a time of last click
(function() {
    var timeOfLastClick = 0;
    document.getElementById("run").addEventListener("click", function(e) {
        var now = new Date().getTime();
        // only process click if more than 2 seconds have passed since last click
        if (now - timeOfLastClick > 2000) {
            // OK to process the click
        }
        timeOfLastClick = now;
    });
})();

有时,您实际上可以将所有代码或几乎所有代码都包含在这样的单个闭包中,并且所有当前的全局变量都会成为闭包内的局部变量,而不是实际的全局变量。 jQuery使用这种技术来声明它使用的许多持久变量,其中没有一个是实际的全局范围的。


使用单个命名空间对象

减少全局变量数的另一种常用方法是使用命名空间概念。在此概念中,您声明一个全局对象并将其他持久变量作为此单个全局对象的属性。这仍然会为您留下一个全局变量,您可以在此单个全局变量中拥有任意数量的属性。

var myNamepaceObject = {};
myNamespaceObject.var1 = "foo";    
myNamespaceObject.var2 = "whatever";

jQuery也使用了这种技术,因为jQuery提供的所有全局可访问函数都可以在jQuery对象中使用,例如jQuery.extend()jQuery.contains()。 jQuery公开了一个单一的全局变量,然后许多其他全局可访问的函数可用作该单个全局对象的属性。


模块模式

通常所说的&#34;模块模式&#34;使用以上两种技术的组合,其中您有一个模块变量,它们都使用属性和闭包变量。

var MODULE = (function () {
    var my = {},
        privateVariable = 1;

    function privateMethod() {
        // ...
    }

    my.moduleProperty = 1;
    my.moduleMethod = function () {
        // ...
    };

    return my;
}());

您可以在以下参考资料中看到对此设计模式的讨论:

JavaScript Module Pattern: In-Depth

Learning Javascript - The Module Pattern

Mastering the Module Pattern

JavaScript module pattern with example

答案 2 :(得分:1)

之前我遇到了同样的问题,但这是一个很大的问题,因为我们有第三方javascript代码,我们的代码存在于客户网站中,所以我们应该找到一种方法来省略全局变量的外观,所以要简短: 使用1个全局变量命名空间,并使所有其他命名空间成为它的特性:

GlobalVariable = {}
GlobalVariable.var1 = "var1"
GlobalVariable.var2 = "var2"

您还可以将其更有用并将其分成几组:

 GlobalVariable.helper = {}
 GlobalVariable.helper.var1 = "var1"
 GlobalVariable.helper.var2 = "var2"

因此您可以在不同的组下使用相同的名称。

如果你想完全省略,你可以使用:

(function(document, window) {
    // all variables here is global only inside the scope
}(document, window));