【问题标题】:Accessing variables from other functions without using global variables从其他函数访问变量而不使用全局变量
【发布时间】:2009-01-02 15:16:50
【问题描述】:

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

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

【问题讨论】:

  • @annakata 因为在 SO 上有不少顽固的用户

标签: javascript global-variables


【解决方案1】:

我认为你最好的选择可能是定义一个 single 全局范围的变量,并将你的变量放在那里:

var MyApp = {}; // Globally scoped object

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

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

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

【讨论】:

  • 您的示例的问题在于,javascript 处理嵌套对象需要更长的时间。 (这需要很长时间:MyApp.something.color.somethingElse
  • Progo,这不是一个真正的问题。
  • 函数var()应该改成bar(),这个微小的语法错误可能会让以后的人头疼。
  • 谢谢,正是我需要的!但我不明白,如果从未调用过foo(),应该如何创建和填充MyApp.color
  • 三联画,感谢您为我的工作保障做出贡献:p
【解决方案2】:

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

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

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

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

function B(r)
{
    use_rand_num(r);
}

【讨论】:

  • 不要污染全局命名空间!您最坏的情况下的回退应该不超过使用单个自定义全局对象创建对象属性
  • 我想出的第四个选项,当时这三个选项都不适合我。 stackoverflow.com/questions/3531080/…(见 Emile 的回答)
  • ps。 pm上面的链接,寻找“Emile”的未经检查的答案
  • 我知道这已经很老了,但我只是想知道,在大型程序中大量使用第三种方法不会导致意大利面条代码吗?
  • 所以这是柯里化?一段时间以来我一直在努力解决这个问题,这是一个非常简单的例子
【解决方案3】:

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

【讨论】:

    【解决方案4】:

    考虑使用命名空间:

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

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

    【讨论】:

    • 超级棒的答案!最后是一个类似于其他语言的类结构:)
    • 这很好,这应该是公认的答案。第二种模式显然被称为“对象模式的静态命名空间”,如下所述:javascriptweblog.wordpress.com/2010/12/07/…
    【解决方案5】:

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

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

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

    【讨论】:

    • -1。这不仅不是柯里化的例子,而且对于这个问题的答案太复杂了。
    • @triptych:我不同意。对于此类问题,这是一个完全有效且有趣的解决方案,并且完全是 currying (dustindiaz.com/javascript-curry)
    • +1 令人困惑...然后启发!一旦我清楚地看到myCallback 是对getMyCallback 返回的函数的引用,randomValue 已经设置。使用getRand 也很有指导意义,因为我看到多次调用myCallBack(1) 将返回相同的值,因此myCallback 等于从getMyCallBack(getRand()) 返回的值,而不仅仅是对函数本身的引用。大声说出来很有帮助:)
    【解决方案6】:

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

    返回您希望在 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();
    

    【讨论】:

      【解决方案7】:

      另一种方法是我从 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
      

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

      【讨论】:

        【解决方案8】:

        如果另一个函数需要使用一个变量,你可以将它作为参数传递给函数。

        此外,全局变量本身并不讨厌和邪恶。只要使用得当,就没有问题。

        【讨论】:

        • 全局变量在 Javascript 中是极其邪恶的。 -1.
        【解决方案9】:

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

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

        【讨论】:

          【解决方案10】:

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

          这是答案(重要提示:这不是选中的答案,而是我“Emile”的答案):

          How to get a variable returned across multiple functions - Javascript/jQuery

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2018-03-07
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2013-09-13
            • 1970-01-01
            • 2020-10-12
            相关资源
            最近更新 更多