我到处都读到了全局变量不好的地方,应该使用替代方法。特别是在Javascript中,我应该选择哪种解决方案。 function globalVariables(Variable,Value),否则附加ValueVariable。如果不带参数调用函数(Value),它将返回数组。也许如果仅使用一个参数(function globalVariables())触发该函数,它将返回数组中function globalVariables(Variable)的值。

您怎么看?我想听听您使用全局变量的替代解决方案和参数。

如何使用Variable


function append(){
    globalVariables("variable1","value1"); //globalVariables() would append variable1 to it's local array.
};

function retrieve(){
    var localVariable1 = globalVariables("variable1"); //globalVariables() would return "value1".
};

function retrieveAll(){
    var localVariable1 = globalVariables(); //globalVariables() would return the globalVariable()'s entire, local [persistently stored between calls] array.
};

function set(){
    globalVariables("variable1","value2"); //globalVariables() would set variable1 to "value2".
};


这是Singleton模式的BTW吗?变量。因此,第一个函数不能将变量作为参数传递给后一个函数,因为永远不会从第一个函数调用它。

谢谢您,我感谢您的所有帮助!

评论

我认为您不太了解为什么它们不好

@Yacoby:我想我[李的答案解释了很多],但是如果您感到不满意,请详细说明。在这种情况下我应该使用什么解决方案?

我必须在这里同意@Yacoby。您在示例中有点重塑了全局变量,因此让您回到“全局变量不好”的步骤之一。

好的,谢谢Yacoby和Patrick,但是我如何在几个不能互相调用的函数之间保留一个持久变量,以致不能发送参数?
我是否应该将变量值保存在cookie中而不是作为替代?例如

#1 楼

不鼓励在javascript中使用全局变量的主要原因是,在javascript中,所有代码都共享一个全局命名空间,而javascript也隐含了全局变量,即。在本地范围内未明确声明的变量将自动添加到全局名称空间。过度依赖全局变量可能导致同一页面上的各个脚本之间发生冲突(请参阅Douglas Crockford的文章)。

减少全局变量的一种方法是使用YUI模块模式。基本思想是将所有代码包装在一个函数中,该函数返回一个对象,该对象包含需要在模块外部访问的函数,并将返回值分配给单个全局变量。

var FOO = (function() {
    var my_var = 10; //shared variable available only inside your module

    function bar() { // this function not available outside your module
        alert(my_var); // this function can access my_var
    }

    return {
        a_func: function() {
            alert(my_var); // this function can access my_var
        },
        b_func: function() {
            alert(my_var); // this function can also access my_var
        }
    };

})();


现在要在其他模块中使用功能,请使用FOO.a_func()。解决全局名称空间冲突的这种方法只需要更改FOO的名称即可。

评论


太酷了,它将完全重写我的代码,但是我已经完成了,太好了,已经接受了答案。

–乔纳森·奥茨(Jonathon Oates)
2010-4-12的0:05

呵呵-最后两个括号是一个陷阱!没有它们,您将需要引用FOO()。a_func()。啊,现在开始变得有意义了!

– ErichBSchulz
13年4月8日在12:26

所以命名冲突是唯一的原因?还是还有内存使用方面的缺点?

– bhavya_w
2014年9月12日上午8:25

这种做法基本上不是针对库或其他可重用代码的吗?如果您正在为Web应用程序编写本机代码,而该代码通常不会在其他地方使用-并假设您的命名不差,或使用填充全局命名空间的库不好-它在您的Web应用程序中有什么用?只是以某种方式更清洁,而不必在每个模块中缩进所有代码?

– bryc
15年7月8日在7:30

有趣的是,在香草js中,函数调用位于匿名函数周围的括号之外。但是在我所看到的所有node.js模块模式中,函数调用都在这些括号内。这有什么不同吗?如果是这样,那是什么?

–krb686
16年8月14日在15:55

#2 楼

语义学,我的孩子。语义。

从一个全局变量开始:myApp = {};
所有内容都应该包含在其中。唯一的例外是您的AJAX库(有一些极端的例外,例如使用JSONP回调)。

myApp中的属性应该很少。您需要将应用程序属性保存在配置或设置之类的容器中。

myApp = {
    config:{
        prop:1
    },
    settings:{
        prop:2
    },
    widgets:{
        List: function(props){},
        Item: function(props){}
    }
}


那么,您可能在较低的模块,组件,单例和类构造函数中具有更多属性。 (小配件)。

此设置为您带来了额外的好处,即可以从任何其他位置访问任何属性,因为可以通过myApp global获取它。但是,应尽可能使用“ this”,因为查找速度更快。只需直接设置该属性,就不必理会伪获取器/设置器的东西。如果您确实需要吸气剂/吸气剂,请为该特定用途进行编码。

您的示例不起作用的原因是它太通用了,您似乎正在寻找在全球范围内工作的借口空格。

不要对私有变量聪明。它们也很糟糕:
http://clubajax.org/javascript-private-variables-are-evil/

评论


伟大的评论mwilcox。我用这篇文章说服了这里的其他人。

–克里斯
13年5月3日,19:32

这是完成的方式。具有所有必须完全可全局访问的所有变量的单个全局变量。 +1

–welbornio
2014年6月11日15:32

有人知道有一种工具可以帮助将使用全局范围的大型应用程序转换为此类应用程序吗?

–不知道
18年8月20日在20:50

#3 楼

全球国家在几个方面造成问题。一种是代码重用。当您访问某些全局状态时,这意味着组件必须知道其环境(自身外部)。您应尽可能避免这种情况,因为它会使组件变得不可预测。

说我有一个对象可以访问您的globalVariables函数,我想在另一个页面中使用它。我怎么知道定义globalVariables对象,甚至如何定义它?但是,如果您可以将信息传递给构造函数或作为函数的参数,则可以轻松确定对象需要什么。

此外,当您访问或修改全局范围时,也可能会影响其他对象。这就是为什么像jquery这样的库在全局范围内仅使用单个名称的原因(最小可能)。它减少了与其他库冲突的可能性。换句话说,全局范围超出了您的控制范围,因此很危险。

#4 楼


关于原因,请参见例如此处的最高帖子:您在生产企业环境中见过的最EVIL代码是什么?

作为旁注,一个人总是可以执行“全局”代码而不会在全局变量上乱七八糟: br />
(function () {
    var notaglobal = 1;
    alert(notaglobal);
})();
//notaglobal is not defined in this scope        


#5 楼

无论选择哪种语言,使用全局变量通常都是一种不好的做法。我强烈建议不要在严格模式下使用它们。

考虑一下我发现的这段代码:

if (typeof session != 'undefined' && !data.cart.request_status)
  data.input_definitions.passengers =
    inflate_passenger(session, data.input_definitions.passengers);


我需要回过头去问一个低级的程序员,这个session变量是从哪里来的,因为没有代码搜索显示设置在哪里。

我发现公司的另一个软件包设置了全局变量变量。
编码就像一个玩笑:如果您需要解释它,那可能不太好。

使用ES6的变通方法:

如果在Node上,请使用importrequire将所需的内容带入词法范围,不要让人们在不知情的情况下接触您的全局环境。对于浏览器,除非使用Babel转换ES6代码,否则不能使用import

使用Gulp.js进行代码转换的示例:

import {Sesssion} from 'api-core';
const Session = require('api-core').session;


旧的解决方法:

当不能使用ES6功能时使用一堆全局变量的唯一解决方法是仅使用一个,并希望:

// $ npm install --save-dev gulp-babel babel-preset-es2015

// gulpfile.js
const gulp  = require('gulp');
const babel = require('gulp-babel');

gulp.task('transpile', () => {
  return gulp.src('src/app.js')
    .pipe(babel({presets: ['es2015']}))
    .pipe(gulp.dest('dist'));
});

// $ gulp transpile


#6 楼

解决方案的问题在于,这只会使您的代码难以理解,同时仍然保留了全局变量的所有缺点。您链接到的页面涵盖了问题。您提出的解决方案真正解决的唯一问题是名称空间污染,但代价是无法像声明声明一样容易地看到声明了什么全局变量(函数调用)。

解决方案是编写没有全局变量的代码。如果函数需要一个值,则将其作为参数传递。

评论


...,如果对象需要上下文,则将其作为构造函数参数提供。

– Stephen C
2010-4-10 12:23

谢谢,但是在这种情况下,将值作为参数传递是行不通的。我需要各种变量,这些变量可以保持不变,并且可以通过几个函数访问。

–乔纳森·奥茨(Jonathon Oates)
2010-4-10的12:57

#7 楼

本文提到的其他答案大多用匿名函数来解释,


匿名函数难以调试,维护,测试或重用。


这是正常功能的例子。更容易阅读和理解。




 /* global variable example */

    var a= 3, b= 6;
    
    function fwithglobal(){
    console.log(a, b); // 3 6 expected
    }
    
    fwithglobal(); // first call
    
    function swithglobal(){
    var a=9;
    console.log(a, b); // not 3 6 but 9 6
    }
    
    swithglobal(); // second call
    

/* global variable alternative(function parameter) */

    function altern(){
    var a= 3, b= 6; // var keyword needed
      f_func(a,b);
      s_func(a,b);
    }
    
    function f_func(n, m){
    console.log(n, m); // 3 6 expected
    }
    
    function s_func(n, m){
    var a=9;
    console.log(n, m); // 3 6 expected
    }
    
    altern(); // only once 




#8 楼




 var ASHIVA_HandsOffNHS = (function() {
    
    // VARIABLES

    var my_var = 10;


    // PRIVATE FUNCTIONS
    
    function bar() {
        window.alert(my_var + 5);
    }


   // PUBLIC OBJECT

    myObject = {};
    
    myObject['a_func'] = function() {
            my_var += 10;
            window.alert(my_var);
        };
        
    myObject['b_func'] = function() {
            my_var = 0;
            window.alert(my_var);
        };

    return myObject;

})();

ASHIVA_HandsOffNHS.a_func();
ASHIVA_HandsOffNHS.b_func();
ASHIVA_HandsOffNHS.a_func(); 




#9 楼

全局变量很糟糕...如果不加以管理!

全局变量的潜在风险与经常使用的对象准备就绪时所带来的乐趣和生产率一样高。

我不认为应该寻求一个替代方案。相反,我主张一个负责管理这些全局变量的对象,并且随着代码库/组件的成熟,将它们重构出来。

当前答案中未提及的一件事,我认为至关重要的是对DI的理解和IoC容器。这些解决了人们尝试使用全局变量解决的许多问题,但涵盖了普通全局变量无法解决的相关问题,例如对象生命周期。