在javascript中可变提升

Use*_*123 4 javascript

我正在读一些关于Variable Hoisting我无法理解如何学习它的东西.我读了W3C学校的解释.但是,根据示例代码,我无法做出什么是悬挂.

代码1 [这是来自w3c学校的代码]

<!DOCTYPE html>
<html>
<body>

<p id="demo"></p>

    <script>
    var x = 5; // Initialize x
    var y;     // Declare y

    elem = document.getElementById("demo"); // Find an element 
    elem.innerHTML = x + " " + y;           // Display x and y

    y = 7;     // Assign 7 to y

    </script>
       </body>
    </html>
Run Code Online (Sandbox Code Playgroud)

但上面的代码仍然显示'undefined'变量y.

如果我更改代码如下,那么它工作正常.但是,下面的代码是常见的,而不是要理解的不同代码'hoisting'

<script>
var x = 5;  // Initialize x
var y;
y = 7;
elem = document.getElementById("demo"); // Find an element 
elem.innerHTML = x + " " + y;           // Display x and y
</script>
Run Code Online (Sandbox Code Playgroud)

有什么帮助可以理解'变量提升'吗?

T.J*_*der 6

(注:我添加ES2015的简要讨论let,并const在此答案的结束.)

从根本上说,变量提升意味着无论你var在任何给定的范围内看到什么,它就好像它是在范围的最开始.所以这些都是相同的:

function foo() {
    var a = 42;
}

function foo() {
    var a;
    a = 42;
}

function foo() {
    a = 42;
    var a;
}

function foo() {
    var a;
    a = 42;
    var a;
}
Run Code Online (Sandbox Code Playgroud)

它们由JavaScript引擎处理,就像它们一样:

function foo() {
    var a;
    a = 42;
}
Run Code Online (Sandbox Code Playgroud)

这是一个实际使用变量提升的例子,并举一个我称之为隐形全球恐怖 的例子(这是我贫血的小博客上的帖子):

function foo() {
    a = 42;
    b = 67;

    console.log(a); // 42
    console.log(b); // 67

    var a;
}
foo();
console.log(typeof a); // undefined
console.log(typeof b); // number?!
console.log(b);        // 67?!
Run Code Online (Sandbox Code Playgroud)

为什么b存在于外面foo?因为在内部foo,这两行做了很多不同的事情:

a = 42;
b = 67;
Run Code Online (Sandbox Code Playgroud)

第一行设置局部变量a,因为我们声明了它.是的,我们稍后宣布,但我们宣布了.

第二行创建一个隐式全局变量b,因为我们从未b在任何地方声明过foo.

更多(在我的博客上):


ES2015(又名"ES6")介绍letconst.它们的处理方式略有不同var:

  1. 它们具有块范围而不是功能或全局范围.
  2. 声明被提升到块的顶部,但他们没有得到在这一点上任何默认值; undefined只有在逐步执行代码时达到声明时,才会初始化它们(使用或提供的值).

示范点#1(块范围):

function foo() {
    {
        let a = 1;
        console.log(a); // 1
    }
    console.log(a); // ReferenceError: a is not defined
}
foo();
Run Code Online (Sandbox Code Playgroud)

演示第2点:这可以使用var,它不适用于let:

function foo() {
    a = 42; // ReferenceError: a is not defined
    let a;
}
foo();
Run Code Online (Sandbox Code Playgroud)

保留标识符(声明)和何时可以使用它(初始化)之间的时间称为Temporal Dead Zone,在此期间您无法使用该变量.