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

Ver*_*e89 5 javascript architecture variables 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个变量中并在我的脚本中多次调用该变量.在某些情况下,这些变量在其他地方也需要.

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

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

jfr*_*d00 5

将变量放入函数闭包内

消除全局的一种常见方法是将 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
})();
Run Code Online (Sandbox Code Playgroud)

以下是一些用法示例:

// 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;
    });
})();
Run Code Online (Sandbox Code Playgroud)

有时,您实际上可以将所有代码或几乎所有代码封装在一个闭包中,就像这样,并且所有当前的全局变量都成为闭包内的局部变量,而不是实际的全局变量。jQuery 使用这种技术来声明它使用的大量持久变量,但这些变量都不是真正的全局范围的。


使用单个命名空间对象

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

var myNamepaceObject = {};
myNamespaceObject.var1 = "foo";    
myNamespaceObject.var2 = "whatever";
Run Code Online (Sandbox Code Playgroud)

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


模块模式

通常所说的“模块模式”使用了上述两种技术的组合,其中您有一个同时使用属性和闭包变量的模块变量。

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

    function privateMethod() {
        // ...
    }

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

    return my;
}());
Run Code Online (Sandbox Code Playgroud)

您可以在这些参考文献中看到对此设计模式的讨论:

JavaScript 模块模式:深入

学习 Javascript - 模块模式

掌握模块模式

JavaScript 模块模式与示例


mir*_*ixx 5

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

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

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

要改变这一点,您需要以基于对象或组件的方法构建系统,即:

  • 通过问题域中的对象封装数据 + 各自的功能,例如,有一个World包含Avatar, Buildings,Airborne对象等的对象(或您的项目的任何内容)。

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

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

为了促进这一点,我建议使用这些优秀的框架,或一些适合您的运行时环境的等效框架:

  • 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();
   ...
});
Run Code Online (Sandbox Code Playgroud)