是否可以在函数中使用非全局变量?

时间:2013-06-28 15:14:03

标签: javascript

我真的很满意这一点,并没有找到真正解释得很好的答案......

我知道如何从函数中访问全局变量。

myGlobalVariable = [];
function myFunction() {
  myGlobalVariable.push("somedata");
}

现在,如果范围链不是全局的,我如何在范围链上一步访问变量?

myGlobalVariable = [];

function myFunction() {

  var notGlobalVariable = "somedata";

  var myOtherFunction = function() {
    myGlobalVariable.push(notGlobalVariable); // This is what I'd like to be able to do.
  }

}

我知道我可以做类似

的事情
var notGlobalVariable = "somedata";

var myOtherFunction = function(arg) {
  myGlobalVariable.push(arg);
}

myOtherFunction(notGlobalVariable);

但是,只有当notGlobalVariable的值可用时,调用该方式才有效。我希望能够全局调用该函数并使其始终使用notGlobalVariable最初保存的值,而不必传递该值。

修改
好吧,我有点跳过这一枪。我虽然有一个很大的变量范围问题,但显然我的问题是在我的特定代码中我使用变量名arguments代替notGlobalVariable,我应该知道,{{ 1}}被遮蔽并引用传入的参数。我将名称更改为arguments并且它工作正常。遗憾!

3 个答案:

答案 0 :(得分:4)

JavaScript通过创建闭包自动完成。

  • 每个函数都创建自己的范围。
  • 范围是嵌套的,因为函数可以在函数中定义。
  • 每个新的嵌套作用域(“function”)都可以看到在任何父作用域中定义的所有变量(即新函数的创建) 。这称为闭包。
  • 来自任何父作用域的每个变量都是“通过引用” - 子作用域(“functions”)始终可以看到它们的当前值。
  • 函数运行的时间点无关紧要,只是声明它的时间点(参见第一个示例)。
  • 函数中运行的范围无关紧要,只有函数的作用域中定义(参见第二个示例)。

下面

var myGlobalVariable = [];

// define function => creates closure #1
function myFunction() {
  var notGlobalVariable = "somedata";

  // define function => creates closure #2
  var myOtherFunction = function() {
    myGlobalVariable.push(notGlobalVariable);
  }

  // execute function
  myOtherFunction();
}

myFunction();  // myGlobalVariable will be ["somedata"]

您创建了两个范围:

  1. myFunction可以看到myGlobalVariable
  2. myOtherFunction中存储的匿名函数可以看到myGlobalVariablenotGlobalVariable
  3. 现在假设一个小小的变化:

    var myGlobalVariable = [];
    
    // define function => creates closure #1
    function myFunction(callback) {
      var notGlobalVariable = "somedata";
    
      // define function => creates closure #2
      var myOtherFunction = function() {
        myGlobalVariable.push(callback());
      }
    
      // execute function
      myOtherFunction();
    }
    
    // define function => creates closure #3
    function foo() {
      var thisIsPrivate = "really";
    
      // define function => creates closure #4
      return function () {
        return thisIsPrivate;
      }
    }
    
    myFunction(foo());  // myGlobalVariable will be ["really"]
    

    您看到callback函数可以访问thisIsPrivate,因为它是在正确的范围内定义,即使它是在中执行的范围看不到变量。

    同样,callback函数将无法看到notGlobalVariable,即使该变量在执行回调的范围内可见。

    请注意,始终必须对您定义的任何变量使用var。否则变量将是静默全局的,这可能并且将导致难以修复程序中的错误。

答案 1 :(得分:1)

是的,你可以 - 在javascript中一切皆有可能 - 这里是小提琴http://jsfiddle.net/AZ2Rv/

myGlobalVariable = [];

function myFunction() {

  var notGlobalVariable = "somedata";

  // The following assigns a function to a variable
  var myOtherFunction = function() {
    myGlobalVariable.push(notGlobalVariable);
  }

  // The following line was missing in the code in the question so the function
  // was never called and `notGlobalVariable` wasn't pushed into `myGlobalVariable`
  myOtherFunction();
}

// And just to test if it works as expected
myFunction();
alert(myGlobalVariable[0]);

OP的问题实际上存在于他未发布的代码中,但是这个示例代码回答了原始问题 - 闭包仍然按照预期在javascript中工作。

答案 2 :(得分:1)

您可以访问notGlobalVariable内的myOtherFunction。但是,您只是分配myOtherFunction并且从不调用它。请注意,您必须在myOtherFunction内调用myFunction

function myFunction() {

  var notGlobalVariable = "somedata";

  var myOtherFunction = function() {
    myGlobalVariable.push(notGlobalVariable); // This is what I'd like to be able to do.
  }
  //Invoke myOtherFunction()
  myOtherFunction()

}