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

IT技术 javascript global-variables
2021-01-12 16:48:20

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

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

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

你会如何使用 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".
};

这是单例模式BTW?

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

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

6个回答

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

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

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

})();

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

crockford 的文章描述了 z33m 的解决方案yuiblog.com/blog/2006/06/01/global-domination
2021-03-23 16:48:20

语义我的孩子。语义。

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

使用 ES6 的解决方法:

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

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

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

使用 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

旧版解决方法:

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

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

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

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

...如果对象需要上下文,请将其作为构造函数参数提供。
2021-03-24 16:48:20
谢谢,但在这种情况下,将值作为参数传递是行不通的。我需要各种保持持久性并且可以被多个函数访问的变量。
2021-03-29 16:48:20