77

我从很多地方听说全局变量本质上是讨厌和邪恶的,但是在做一些非面向对象的 Javascript 时,我看不出如何避免它们。假设我有一个函数,它使用复杂算法使用随机数和其他东西生成一个数字,但我需要在其他函数中继续使用该特定数字,该函数是回调或其他东西,因此不能成为同一函数的一部分。

如果最初生成的数字是局部变量,则无法从那里访问它。如果函数是对象方法,我可以将数字设为属性,但它们不是,并且更改整个程序结构来执行此操作似乎有些过于复杂。全局变量真的那么糟糕吗?

4

10 回答 10

89

我认为你最好的选择可能是定义一个全局范围的变量,然后在那里转储你的变量:

var MyApp = {}; // Globally scoped object

function foo(){
    MyApp.color = 'green';
}

function bar(){
    alert(MyApp.color); // Alerts 'green'
} 

没有人应该因为你做了上述那样的事情而对你大喊大叫。

于 2009-01-02T15:24:13.383 回答
62

要使函数 A 中计算的变量在函数 B 中可见,您有三个选择:

  • 使其成为全球性的,
  • 使其成为对象属性,或
  • 从 A 调用 B 时将其作为参数传递。

如果您的程序相当小,那么全局变量还不错。否则我会考虑使用第三种方法:

function A()
{
    var rand_num = calculate_random_number();
    B(rand_num);
}

function B(r)
{
    use_rand_num(r);
}
于 2009-01-02T15:22:21.237 回答
16

考虑使用命名空间:

(function() {
    var local_var = 'foo';
    global_var = 'bar'; // this.global_var and window.global_var also work

    function local_function() {}
    global_function = function() {};
})();

两者local_functionglobal_function可以访问所有局部和全局变量。

编辑:另一种常见模式:

var ns = (function() {
    // local stuff
    function foo() {}
    function bar() {}
    function baz() {} // this one stays invisible

    // stuff visible in namespace object
    return {
        foo : foo,
        bar : bar
    };
})();

现在return可以通过命名空间对象访问 ed 属性,例如ns.foo,同时仍保留对本地定义的访问。

于 2009-01-02T15:33:51.260 回答
9

您要查找的内容在技术上称为柯里化。

function getMyCallback(randomValue)
{
    return function(otherParam)
    {
        return randomValue * otherParam //or whatever it is you are doing.
    }

}

var myCallback = getMyCallBack(getRand())

alert(myCallBack(1));
alert(myCallBack(2));

以上并不完全是一个柯里化函数,但它实现了维护现有值的结果,而无需向全局命名空间添加变量或需要其他一些对象存储库。

于 2009-01-02T15:23:05.010 回答
5

我发现这对于原始问题非常有帮助:

返回您希望在 functionOne 中使用的值,然后在 functionTwo 中调用 functionOne,然后将结果放入一个新的 var 并在 functionTwo 中引用这个新的 var。这应该使您能够在 functionTwo 中使用 functionOne 中声明的 var。

function functionOne() {
  var variableThree = 3;
  return variableThree;
}

function functionTwo() {
  var variableOne = 1;
  var var3 = functionOne();

  var result = var3 - variableOne;

  console.log(variableOne);
  console.log(var3);
  console.log('functional result: ' + result);
}

functionTwo();
于 2014-06-12T08:04:18.770 回答
4

如果另一个函数需要使用变量,则将其作为参数传递给函数。

全局变量也不是天生讨厌和邪恶的。只要使用得当,它们就没有问题。

于 2009-01-02T15:21:27.383 回答
3

如果您有机会重用此代码,那么我可能会努力采用面向对象的视角。使用全局命名空间可能很危险——由于变量名会被重用,您会冒着难以发现错误的风险。通常,我首先使用面向对象的方法,而不是简单的回调,这样我就不必重新编写。每当您在 javascript 中拥有一组相关函数时,我认为它都是面向对象方法的候选者。

于 2009-01-02T15:22:24.993 回答
2

另一种方法是我从 Douglas Crockford 论坛帖子 ( http://bytes.com/topic/javascript/answers/512361-array-objects ) 中选择的。这里是...

道格拉斯·克罗克福德写道:

2006 年 7 月 15 日

“如果你想通过 id 检索对象,那么你应该使用一个对象,而不是一个数组。由于函数也是对象,你可以将成员存储在函数本身中。”

function objFacility(id, name, adr, city, state, zip) {

    return objFacility[id] = {

        id: id,
        name: name,
        adr: adr,
        city: city,
        state: state,
        zip: zip

    }
}

objFacility('wlevine', 'Levine', '23 Skid Row', 'Springfield', 'Il', 10010);

“该对象可以通过”获得

objFacility.wlevine

现在可以从任何其他函数中访问对象属性。

于 2013-02-23T15:48:50.877 回答
1

我不知道您的问题的具体情况,但如果函数需要该值,那么它可以是通过调用传递的参数。

全局变量被认为是不好的,因为全局变量状态和多个修饰符会产生难以遵循的代码和奇怪的错误。对许多演员来说,摆弄某些东西会造成混乱。

于 2009-01-02T15:23:26.570 回答
1

您可以使用自定义 jQuery 事件完全控制 javascript 函数的执行(并在它们之间传递变量)....有人告诉我,这在这些论坛中是不可能的,但我得到了一些可以做到这一点的东西(即使使用一个ajax调用)。

这是答案(重要提示:这不是经过检查的答案,而是我“Emile”的答案):

如何获取跨多个函数返回的变量 - Javascript/jQuery

于 2010-08-22T07:54:29.377 回答