【问题标题】:Why sometimes defining variable after calling the variable doesn't give undefined?为什么有时在调用变量后定义变量不会给出未定义?
【发布时间】:2014-06-21 04:16:43
【问题描述】:

我有两个sn-ps,为什么第一个给出值第二个给出未定义

片段 1:

function sayAlice() {
    var sayAlert = function() { alert(alice); }
    var alice = 'Hello Alice';
    return sayAlert;
}
var hi = sayAlice() ;
hi();//alert Hello Alice

片段 2:

alert(i); // alert undefined
var i = 1; 

【问题讨论】:

  • 在第二个示例中切换行,它可以工作
  • 是的...我知道。我想知道为什么在第一个 sn-p 中它起作用了
  • 查看我在回答中提供的链接,您将了解。

标签: javascript


【解决方案1】:

发生这种情况是因为在第二个 sn-p 中,变量 'i' 没有在执行警报的那一刻定义,但在第一个 sn-p 中,发生的情况是在该行中

var sayAlert = function() { alert(alice); }

您将 'sayAlert' 定义为一个函数,但此时该函数并未执行。之后,定义变量“alice”,然后返回“sayAlert”,此时,警报执行完毕,变量“alice”已经有了值。

【讨论】:

    【解决方案2】:

    您有 inside 匿名函数,它是 closure。闭包有点像他们的环境,可以从中访问局部变量。

    这个MDN article 描述了一个与你非常相似的案例。

    还可以查看What exactly does “closure” refer to in JavaScript? SO 帖子。

    【讨论】:

      【解决方案3】:

      你的问题是这样的:

      为什么有时在调用变量后定义变量不 给未定义?

      然后你提供这个作为例子:

      alert(i); // alert undefined
      var i = 1; 
      

      它会提醒undefined,因为您在定义i 之前发出alert()

      在第一个例子中:

      function sayAlice() {
          var sayAlert = function() { alert(alice); }
          var alice = 'Hello Alice';
          return sayAlert;
      }
      sayAlice()() //alert Hello Alice
      

      同样的行为是意料之中的,但您调用sayAlice 的奇怪方式似乎与()() 发生了两次。这基本上意味着虽然它可能很快发生,但第一次调用sayAlice() 将设置alice 变量,但alert 很可能发生在通过sayAlice()() 调用的第二次迭代中。

      等等。再看一遍,这就是第一个例子中发生的事情。这只是将sayAlert 定义为一个函数,但实际上并没有运行它:

      var sayAlert = function() { alert(alice); }
      

      但是你这样做:

      var alice = 'Hello Alice';
      

      它为alice 赋值。然后你终于做到了:

      return sayAlert;
      

      这发生在前两项之后。意思是,在第三行定义了一个函数,然后定义了一个变量,但它只在最后一行出现。

      这对我来说很有意义。但是 sayAlice()() 和双 () 看起来很奇怪。

      【讨论】:

      • 我有两个 sn-ps,第一个没有 undefined 而第二个没有
      • @Blake 正确。有趣的谜题。看看我在最新编辑中的分析。
      • @JakeGould - 这不是谜题。这是 JS closure 的记录行为。
      • @PM77-1 像这样以特殊方式实现的文档化功能是一个难题。
      【解决方案4】:

      所有变量声明在运行之前都由 javascript 解释器移到其作用域的顶部。这意味着这样的事情:

      function sayAlice() {
          var sayAlert = function() { alert(alice); }
          var alice = 'Hello Alice';
          return sayAlert;
      }
      sayAlice()() //alert Hello Alice
      

      相当于:

      function sayAlice() {
          var sayAlert, alice;
          sayAlert = function() { alert(alice); }
          alice = 'Hello Alice';
          return sayAlert;
      }
      sayAlice()() //alert Hello Alice
      

      当您调用sayAlice()() 时,它首先解析sayAlice(),它返回函数sayAlert,绑定到变量alice,其值为“Hello Alice”。只要内部函数可以访问外部变量,该变量就会保留其范围。因此,分配 sayAlert 之后的行,即alice = 'Hello Alice' 修改了 sayAlert 函数引用的变量。那么在调用点你会得到预期的结果“Hello Alice”。

      【讨论】:

      • “所有变量声明都移到其作用域的顶部……”很有趣。看我的回答。当var sayAlert = function() { alert(alice); } 不只是一个变量被分配了一个函数但函数直到return sayAlert; 才执行?
      • 我已经修改了我的答案。它的要点是不:变量没有分配给函数。该函数读取对该变量的引用,该变量在函数声明后可能已在其他地方更改。
      【解决方案5】:

      试试这段代码,你会得到完全不同的结果...

      function sayAlice() {
          var sayAlert = function() { alert(alice); }
          return sayAlert;
          var alice = 'Hello Alice';
      }
      

      因为在调用函数时alice 是未定义的。在您的示例中,定义了 alice

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-05-31
        • 2021-12-16
        • 1970-01-01
        相关资源
        最近更新 更多