【问题标题】:Different ways of writing a function bringing undesired effects in JavaScript?编写函数的不同方式会在 JavaScript 中带来不良影响?
【发布时间】:2025-11-25 21:45:01
【问题描述】:

更新:

问题已解决!我意识到这是由于“吊装”造成的。基本上,JavaScript 解释器解析代码并在函数的开头声明所有变量(但不初始化它们)。这就是为什么第二个示例不起作用的原因。因为 JavaScript 解释器在函数开头声明了var changed;,但在到达代码主体之前不会初始化它

对于函数声明,就像第一个示例一样,JavaScript 不是像第二个示例那样仅向上移动变量名,而是向上移动(或“提升”)整个 父函数开头的函数,这就是它起作用的原因!

无论如何,我写这个供个人参考并感谢您的回答......


这个有效: http://jsbin.com/emarat/7/edit

$(function(){
  $name = $('#test');
  $name.change(changedName);

  function changedName (e){
      console.log('e: ', e); 
      console.log('e.currentTarget: ', e.currentTarget); 
      console.log('$(e.currentTarget).val(): ', $(e.currentTarget).val());
      $('#test-display').text($(e.currentTarget).val());
    }
});

但这个没有: http://jsbin.com/emarat/9/edit

$(function(){
  $name = $('#test');
  $name.change(changed);

  var changed = function(e){
      console.log('e: ', e); 
      console.log('e.currentTarget: ', e.currentTarget); 
      console.log('$(e.currentTarget).val(): ', $(e.currentTarget).val());
      $('#test-display').text($(e.currentTarget).val());
    };
});

为什么?

【问题讨论】:

    标签: javascript scope hoisting


    【解决方案1】:

    后一种等价于:

    $(function(){
      var changed;
      $name = $('#test');
      $name.change(changed);
    
      changed = function(e){
          //...
        };
    });
    

    这很明显为什么它不起作用。使用时,changed 变量尚未初始化(undefined)。

    但如果你使用function yourFunctionName() 语法声明一个函数,它在整个范围内都可用。 (在 JavaScript 中,它是父函数。)否则就不可能在声明之前使用函数。它被称为吊装

    另见:

    【讨论】:

    • @Farmor 不为空,但未定义。
    • @TomaszNurkiewicz:不客气——我一直在努力区分在 JavaScript 中创建函数的两种方式,你对提升的解释帮助我进一步理解它。我只是想为像我这样的大脑迟钝的人添加一些明确的细节。
    【解决方案2】:

    因为变量是在使用后定义的。

    var a = 1;
    var c = a + b;
    var b = 2;
    

    您不会期望该代码会运行。

    【讨论】:

      【解决方案3】:

      第一个定义了作用域中的一个函数。第二个创建了一个内联函数并将对它的引用存储在局部变量changed 中。问题是你使用后填充变量。

      这可行:

      $(function(){
        var changed = function(e){
            console.log('e: ', e); 
            console.log('e.currentTarget: ', e.currentTarget); 
            console.log('$(e.currentTarget).val(): ', $(e.currentTarget).val());
            $('#test-display').text($(e.currentTarget).val());
        };
      
        $name = $('#test');
        $name.change(changed);
      });
      

      http://jsbin.com/emarat/11/edit

      【讨论】: