首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在消除全局变量方面需要建议/帮助

问在消除全局变量方面需要建议/帮助
EN

Stack Overflow用户
提问于 2015-04-19 16:01:33
回答 3查看 2.2K关注 0票数 6

是的,这是另一个关于全局变量的话题。我找了不少关于他们的事。但是大部分的主题都是关于为什么不使用全局变量,我确信我不应该使用,我更想知道如何不使用它们,而且我仍然不确定。

我正在做一个项目,它能创造奇迹,但我目前使用的是大约50个全局变量,而且这个数字还在不断上升。现在,我已经把事情分成了多个.js文件。像load_chunks.js,load_images.js,render_map.js,player_actions.js,input.js一样,根据它们的用途来扩展它们。我把所有的全局变量都放进了settings.js里。

目前,我使用这些全局变量的原因如下:

  1. 基于加载后变化不大或根本不变化的其他全局变量进行计算。通过这样做一次,并将其存储在一个全局变量中,我就不必再重复计算了。如果我没有将它存储在(全局)变量中,Javascript将不得不每秒钟进行多次计算,在某些情况下甚至高达每秒几千次。
  2. 当许多函数都需要全局变量时。就像这个世界变量,我用它来保存世界外观的数据。这个变量是一个多维数组。比如世俗。Load_chunks.js向该变量添加更多数据,如果移动得太远,则删除数据。这个变量在render_map.js中也是必需的,用于创建映射,在player_action.js中也是必需的,以查看是否可以在特定位置上执行步骤。
  3. 设置;因此,除非我在脚本中更改设置,否则变量中的数字将保持不变。我没有遍历我的脚本,经过长时间的搜索并思考数字是什么,而是手动更改数字,而是将这个数字放入一个变量中,并在脚本中多次调用该变量。在某些情况下,这些变量在其他地方也是需要的。

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

那么,我如何摆脱我的全局变量,或者我不应该?我希望你能向我展示或为我写一个脚本示例(或链接到它),说明我应该如何做。这是我学习最快的方法。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2015-04-19 16:06:48

将变量放入函数闭包中

消除全局的一个常见方法是在函数闭包内放置:

代码语言:javascript
复制
(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
})();

下面是一些使用示例:

代码语言:javascript
复制
// 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使用这种技术来声明它使用的许多持久性变量,其中没有一个是实际的全局范围的。

使用单个名称空间对象

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

代码语言:javascript
复制
var myNamepaceObject = {};
myNamespaceObject.var1 = "foo";    
myNamespaceObject.var2 = "whatever";

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

模块模式

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

代码语言:javascript
复制
var MODULE = (function () {
    var my = {},
        privateVariable = 1;

    function privateMethod() {
        // ...
    }

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

    return my;
}());

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

JavaScript模块模式:深度

学习Javascript -模块模式

掌握模块模式

JavaScript模块模式的实例

票数 4
EN

Stack Overflow用户

发布于 2015-04-19 16:57:46

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

load_chunks.js, load_images.js, render_map.js, player_actions.js, input.js,强烈暗示了一个过程实现,即您的体系结构可能有几个功能块,并且您在这些函数之间传递数据。这就是你的全局变量的来源。

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

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

  • 按问题域中的对象封装数据+各自的函数,例如,有一个World对象,其中包含Avatar、Buildings、Airborne对象等(或者您的项目是关于什么的)。
  • 将问题域的逻辑与视图逻辑分离(例如使用MVC架构)
  • 然后,您的项目通过本质上在视图和模型对象之间交换消息来组织视图和模型对象之间的交互。

为了方便这一点,我建议使用这些很好的框架,或者适合您的运行时环境的一些类似的框架:

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

码结构

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

我希望你能给我看一下,或者给我写一个脚本例子。

代码语言:javascript
复制
/* 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();
   ...
});
票数 5
EN

Stack Overflow用户

发布于 2015-04-19 16:09:16

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

代码语言:javascript
复制
GlobalVariable = {}
GlobalVariable.var1 = "var1"
GlobalVariable.var2 = "var2"

您还可以使它更有用,并将其分成几个组:

代码语言:javascript
复制
 GlobalVariable.helper = {}
 GlobalVariable.helper.var1 = "var1"
 GlobalVariable.helper.var2 = "var2"

所以你可以在不同的组中使用相同的名字。

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

代码语言:javascript
复制
(function(document, window) {
    // all variables here is global only inside the scope
}(document, window));
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29732219

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档