【问题标题】:Hoisting order of precedence and variable mutation提升优先级和可变变异
【发布时间】:2019-05-22 19:07:27
【问题描述】:

当涉及到提升和变量突变时,我正在尝试解决一些问题。

  1. 变量赋值优先于函数声明
  2. 函数声明优先于变量声明

根据https://scotch.io/tutorials/understanding-hoisting-in-javascript,函数声明被提升到变量声明之上,而不是变量赋值之上。这非常令人困惑,因为我认为只有变量声明和函数声明会被提升。

var double = 22;

function double(num) {
 return (num*2);
}

console.log(typeof double); // Output: number

所以提升它应该看起来像

function double(num) {
  return (num*2);
}

var double;
double = 22;


console.log(typeof double); // Output: number

如果变量赋值优先于函数声明,为什么 double = 22 不在函数声明之上?另一个例子

var double;

function double(num) {
  return (num*2);
}

console.log(typeof double); // Output: function

通过将函数提升到变量声明上方,控制台应该记录 undefined 不是吗?使用变量变异,最后的赋值是程序应该执行的。

【问题讨论】:

  • 变量名称声明被提升,但变量assignment(带有=)永远不会被提升
  • 那么“变量赋值优先于函数声明”是什么意思呢?
  • @larryburns 这根本没有意义,真的。赋值和声明是两个完全不相关的东西,它们不会“优先于”彼此。我想这应该意味着您始终可以分配一个可变变量,并且之后它将保存分配的值,而不管该变量的声明位置/方式(使用varfunction)。
  • 谁能解释在我的上一个示例中,即使函数被提升到变量声明之上,输出仍然是函数而不是未定义?
  • @larryburns 因为“优先”不是指顺序,如“被提升到另一个之上”。对于我们的目的,声明实际上没有任何顺序,所有变量都是一次创建的(就是“提升”的实际含义)。优先级是指初始化变量的值,undefined 用于vars,函数对象用于functions。该规则意味着当有一个与var 声明同名的function 声明时,该变量被初始化为一个函数。

标签: javascript


【解决方案1】:

根据 MDN:https://developer.mozilla.org/en-US/docs/Glossary/Hoisting#Only_declarations_are_hoisted

JavaScript 只提升声明,而不是初始化。

因此,让我们重写您的示例以便更好地理解:

1.

var double = 22

function double(num) {
  return (num*2)
}

console.log(typeof double)

这可以读作:

// hoisted
var double

function double(num) {
  return (num*2)
}

// initialise
double = 22

console.log(typeof double)

2 & 3 可以按照您编写它们的顺序完全阅读。在 2) 初始化发生在最后,所以它输出Number。 3)中根本没有初始化,所以函数最后声明,所以输出Function

所以你对第三个例子的困惑似乎是理解声明和初始化之间的区别。


编辑:订购肯定有一些混淆(因此写this can be read like..)。虽然 javascript 在技术上首先提升了函数,但您仍然应该阅读我编写的代码,因为函数优先于变量声明。换句话说,虽然从技术上讲,提升是:

function double(num) {
  return (num*2);
}    

var double;    

console.log(typeof double); // Output: function

函数仍然优先,所以最好反过来读。

【讨论】:

  • 函数声明被提升到变量声明之上。我的上一个示例中没有初始化。如果最后一个双精度类型是文档中的变量,它应该记录为未定义,但它记录为函数。
  • 更新了我的答案。
【解决方案2】:

(来自cmets)

如果变量赋值优先于函数声明,为什么double = 22不在函数声明之上?

变量名声明被提升,但赋值 (=) 从未提升。

那么“变量赋值优先于函数声明”是什么意思呢?

这完全没有意义,真的。赋值和声明是两个完全不相关的东西,它们不会“优先”于彼此。我想这应该意味着您始终可以分配一个可变变量,并且之后它将保持分配的值,而不管该变量在何处/如何声明(使用 var 或函数)。

在我的上一个示例中,即使函数被提升到变量声明之上,输出仍然是函数而不是未定义?

因为“优先”不是指顺序,如“被提升在另一个之上”。对于我们的目的,声明实际上没有任何顺序,所有变量都是一次创建的 (that's what "hoisting" actually means)。

优先级是指初始化变量的值,undefined 用于vars,函数对象用于functions。该规则意味着当存在与var 声明同名的function 声明时,则使用函数初始化变量。

【讨论】:

    【解决方案3】:

    这应该澄清是什么意思:

    var myVar = 1;
    
    outerFunc1();
    outerFunc2();
    
    
    function outerFunc1()
    {
    
      innerFunc();    // works due to hoisted declaration
    
      function innerFunc()
      {
        console.log(myVar);
      }
    
      var innerFunc;  // function declarations take precedence
    
      innerFunc();    // works even if var innerFunc is declared
    }
    
    function outerFunc2()
    {
    
      innerFunc();    // outputs undefined since myVar is redeclared locally (hoisted)
    
      function innerFunc()
      {
        console.log(myVar);
      }
    
      var myVar = 2;  // local declaration (AND initialisation)
    
    
      var innerFunc;  // function declaration take precedence
    
      innerFunc();    // outputs 2 even if var innerFunc is declared
    
      innerFunc = 1;  // this overwrites the function
      innerFunc();    // gives an error 'not a function'.
    }

    【讨论】:

    • 不清楚您所说的“在本地重新声明”是什么意思。
    • @Bergi 你不明白什么? var myVar 在全局范围内声明,在函数范围内重新声明为局部变量。
    • 哦,你的意思是它是在outerFunc2 中声明的,而不是在注释行中被调用的innerFunc 中。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-18
    • 2016-11-02
    • 2021-07-23
    • 1970-01-01
    • 2018-03-07
    相关资源
    最近更新 更多