javascript中使用var关键字的箭头函数与同名混淆的正则函数

Arrow function using var keyword and regular function with same name confusion in javascript

为什么这个记录 1 ?这让我感到困惑,任何人都可以解释一下吗?

(function(){

  var hello = () => {
    console.log(1);
  }

  function hello () {
    console.log(2);
  }
  return hello()
})()

函数声明(以 function functionName( 开头的语句)被提升到它们封闭范围的顶部,并首先分配给它们的函数名称标识符,然后在该范围内运行任何其他内容.. [= 赋值14=] 没有。

它是一个箭头函数这一事实并不特别重要 - 在同一点的 function 赋值会产生相同的结果。

(function(){

  var hello = function() {
    console.log(1);
  }

  function hello () {
    console.log(2);
  }
  return hello()
})()

您的代码等同于

(function(){
  // hello identifier gets created at the very beginning
  var hello;
  
  // hoisted function declaration assigns to `hello`:
  hello = function hello () {
    console.log(2);
  }
  
  // assignment with =, not hoisted, assigns to `hello`
  hello = () => {
    console.log(1);
  }
  
  return hello()
})()

我建议至少使用 ES2015+ 语法,这将有助于防止您发生此类事故 - 如果您使用 letconst,它将禁止重新声明变量。

(function(){

  let hello = () => {
    console.log(1);
  }

  function hello () {
    console.log(2);
  }
  return hello()
})()

因为:

  • 函数声明在与 var 声明
  • 相同的绑定环境中创建标识符(更具体地说,“绑定”)
  • var 对已存在的绑定的声明不是错误
  • 函数声明在进入函数或全局范围(“提升”)时进行处理,因此它们首先分配给绑定

因此您的代码正在创建一个绑定,将 declared 函数分配给它,然后用箭头函数覆盖该值。有效:

(function(){
    // Declaration of the var-scoped binding happens first
    var hello;
    // Then the function declaration is processed, assigning
    // the function to the binding
    hello = function hello() {
        console.log(2);
    };
    // Then the step-by-step code begins and processes
    // the assignment
    hello = () => {
        console.log(1);
    };
    return hello();
})();


旁注:var 实际上已弃用,没有理由在现代代码中使用它。相反,请使用 letconst。他们有更理性的行为:

  • 它们是块作用域的,而不是函数作用域或全局作用域的(除非它们出现在函数或全局作用域的顶层)
  • 重复声明是错误的(包括 letconst 声明会与 var 风格的声明(如函数声明)冲突)
  • 在全局范围内,它们位于嵌套在全局 var 范围内的内部范围内,并且不在全局对象上创建属性

你的例子会给你一个很好的,有用的错误 letconst:

(function(){
    let hello = () => {
        console.log(1);
    };

    function hello () {
        console.log(2);
    }
    
    return hello();
})()