Javascript 我听说全局变量不好,我应该使用什么替代解决方案?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2613310/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 01:09:07  来源:igfitidea点击:

I've Heard Global Variables Are Bad, What Alternative Solution Should I Use?

javascriptglobal-variables

提问by Jonathon Oates

I've read all over the place that global variables are badand alternatives should be used. In Javascript specifically, what solution should I choose.

我到处都读到全局变量不好,应该使用替代方法。特别是在 Javascript 中,我应该选择什么解决方案。

I'm thinking of a function, that when fed two arguments (function globalVariables(Variable,Value)) looks if Variable exists in a local array and if it does set it's value to Value, else, Variableand Valueare appended. If the function is called without arguments (function globalVariables()) it returns the array. Perhaps if the function is fired with just one argument (function globalVariables(Variable)) it returns the value of Variablein the array.

我正在考虑一个函数,当输入两个参数 ( function globalVariables(Variable,Value))时,它会查看本地数组中是否存在 Variable ,如果它确实将其值设置为Value,否则VariableValue附加。如果不带参数 ( function globalVariables())调用该函数,则它返回数组。也许如果函数只用一个参数 ( function globalVariables(Variable))触发,它会返回Variable数组中的值。

What do you think? I'd like to hear your alternative solutions and arguments for using global variables.

你怎么认为?我想听听您使用全局变量的替代解决方案和论据。

How you would use globalVariables();

你会如何使用 globalVariables();

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".
};

Is this a Singleton PatternBTW?

这是单例模式BTW?

In this specific scenario a function may set a variable at one point in time, and much later another function, maybe when a user submits a form, will need to get that variable. Therefore the first function couldn't pass the variable as an argument to the later function as it would never be called from the first.

在这个特定的场景中,一个函数可能会在某个时间点设置一个变量,然后另一个函数(可能在用户提交表单时)需要获取该变量。因此第一个函数不能将变量作为参数传递给后面的函数,因为它永远不会从第一个函数中被调用。

Thank you, I appreciate all your help!

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

回答by z33m

The primary reason why global variables are discouraged in javascript is because, in javascript all code share a single global namespace, also javascript has implied global variables ie. variables which are not explicitly declared in local scope are automatically added to global namespace. Relying too much on global variables can result in collisions between various scripts on the same page (read Douglas Crockford's articles).

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

One way to reduce global variables is to use the YUI module pattern. The basic idea is to wrap all your code in a function that returns an object which contains functions that needs to be accessed outside your module and assign the return value to a single global variable.

减少全局变量的一种方法是使用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
        }
    };

})();

now to use functions in your module elsewhere, use FOO.a_func(). This way to resolve global namespace conflicts you only need to change the name of FOO.

现在要在其他地方使用模块中的函数,请使用FOO.a_func(). 这种解决全局命名空间冲突的方法您只需要更改FOO.

回答by mwilcox

Semantics my boy. Semantics.

语义我的孩子。语义。

Start with one global: myApp = {}; Everything should be in that. The only exception would be your AJAX library (there are some extreme exceptions like working with JSONP callbacks).

从一个全局开始:myApp = {}; 一切都应该在那。唯一的例外是你的 AJAX 库(有一些极端的例外,比如使用 JSONP 回调)。

There should be very few properties in myApp. You'll want to hold your application properties in containers such as config or settings.

myApp 中的属性应该很少。您需要将应用程序属性保存在容器中,例如 config 或 settings。

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

Then you may have more properties in lower modules, components, singletons and Class constructors (widgets).

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

This setup gives you the added benefit of being able to access any property from any other location since you can get it with the myApp global. However, you should use "this" whenever possible because the lookup is faster. And just set the property directly, don't bother with the pseudo getter/setter stuff. If you really need a getter/setter, code it for that specific use.

此设置为您提供了能够从任何其他位置访问任何属性的额外好处,因为您可以通过 myApp 全局获取它。但是,您应该尽可能使用“this”,因为查找速度更快。只需直接设置属性,不要理会伪 getter/setter 的东西。如果您确实需要一个 getter/setter,请针对该特定用途对其进行编码。

The reason your example doesn't work is it's too generic and you seem to be looking for an excuse to work in the global space.

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

And don't get clever with private variables. They're bad too: http://clubajax.org/javascript-private-variables-are-evil/

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

回答by Lee

Global state causes problems in several areas. One is code reuse. When you access some global state that means the component must be aware of it's environment(something outside of itself). You should avoid this as much as possible, because it makes the component unpredictable.

全局状态在多个领域引起问题。一是代码重用。当您访问某个全局​​状态时,这意味着组件必须知道它的环境(自身之外的东西)。您应该尽可能避免这种情况,因为它会使组件变得不可预测。

Say I have an object that accesses your globalVariables function and I want to use it in another page. How do I know to define the globalVariables object or even how to define it? However if you can pass the information into a constructor or as an argument to a function then I can easily determine what is required by the object.

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

Also when you access or modify the global scope then you risk affecting other objects. This is why libraries like jquery use only a single name on the global scope(the least possible). It lessens the possibility of conflict with other libraries. In other words the global scope is out of your control, so it is dangerous.

此外,当您访问或修改全局范围时,您可能会影响其他对象。这就是为什么像 jquery 这样的库在全局范围内只使用一个名称(尽可能少)。它减少了与其他库发生冲突的可能性。换句话说,全局作用域是你无法控制的,所以它很危险。

回答by Andras Vass

You really don't want to do this.
As to why, see e.g. the top post here: What is the most EVIL code you have ever seen in a production enterprise environment?

你真的不想这样做。
至于为什么,请参阅例如这里的顶级帖子: 您在生产企业环境中见过的最邪恶的代码是什么?

As a side note, one can always execute "global" code without littering the place with globals:

作为旁注,人们总是可以执行“全局”代码,而不会在全局变量中乱扔垃圾:

(function () {
    var notaglobal = 1;
    alert(notaglobal);
})();
//notaglobal is not defined in this scope        

回答by nicooga

Using global variables is generaly speaking a bad practice, regardless of the language of choice. They are not even (easily) allowed to use when at strict mode, which I highly recommend.

无论选择哪种语言,使用全局变量通常都是一种不好的做法。在严格模式下甚至(很容易)不允许使用它们,我强烈推荐。

Consider this piece of code I found:

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

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

I needed to turn around and ask a felow programmer where did this sessionvariable came from, as no code search showed up where was set.

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

I turned out another package from the company sets the global variable. Code it's like a joke: if you need to explain it it's probably not that good.

我发现公司的另一个包设置了全局变量。代码就像一个笑话:如果你需要解释它可能不是那么好。

Workaround using ES6:

使用 ES6 的解决方法:

If at Node, use importor requireto bring the desired stuff into lexical scope, don't let people touch your global environment without you knowing it.

如果在 Node 上使用importrequire将所需的东西带入词法范围,请不要让人们在您不知情的情况下接触您的全局环境。

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

If you are at the frontend delivering code for the browser you can't use importunless you transpile your ES6 code using Babel.

如果您在为浏览器交付代码的前端,import除非您使用Babel转译您的 ES6 代码,否则您将无法使用。

Example transpiling using Gulp.js:

使用 Gulp.js 进行编译的示例:

// $ 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

Legacy workaround:

旧版解决方法:

When using ES6 features is not an option the only workaround to using a bunch of global variables, is using only one, and have hope:

当使用 ES6 特性不是一种选择时,使用一堆全局变量的唯一解决方法是只使用一个,并且有希望:

// scripts/app.js
var MyApp = {
  globals: {
    foo: "bar",
    fizz: "buzz"
  }
};

回答by Yacoby

The issue with your solution is that it just makes you code harder to understand while still keeping all the downsides of global variables. The page you linked to covers the problems. The only problem your proposed solution really solves is namespace pollution but at the cost of not being able to see what global variables are declared as easily as the declaration is a function call).

你的解决方案的问题在于它只会让你的代码更难理解,同时仍然保留了全局变量的所有缺点。您链接到的页面涵盖了问题。您提出的解决方案真正解决的唯一问题是命名空间污染,但代价是无法像声明是函数调用一样轻松查看声明了哪些全局变量)。

The solution is to write code without global variables. If a function needs a value pass it as a argument.

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

回答by Guspan Tanadi

Other answer most explain with anonymous function as thisarticle mention,

其他答案匿名功能,因为大多数解释文章提到,

Anonymous functions are difficult to debug, maintain, test, or reuse.

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

Here are example with normal function. It's easier to read and understand.

这是具有正常功能的示例。它更容易阅读和理解。

/* 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

回答by Rounin

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();

回答by SystematicFrank

Global variables are bad... if left unmanaged!

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

The potential risks of global variables is as high as the pleasure and productivity gains of having frequently used objects ready to use.

全局变量的潜在风险与频繁使用的对象随时可用所带来的乐趣和生产力收益一样高。

I don't believe one should seek a single alternative. Instead I advocate for one object in charge of managing those globals and as the code base/component matures, refactor them out

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

One thing not mentioned in the current answers which I think is critical is an understanding of DI and IoC containers. These address many of the problems people try to solve with global variables, but covering related concerns that plain globals can't, like object life cycles.

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