JavaScript变量提拔

题目

有些朋侪可能会以为javascript的代码是从上到下,一行一行的诠释实行的。假如根据如许的思绪,在有些状况下浏览代码会获得毛病的结果,斟酌以下代码:

a = 2;
var a;
console.log(a);

console.log(a)应当输出什么呢?有些开发者以为会输出undefined,由于var a在’a = 2’以后,变量a被反复定义了,然则没有被赋值,所以是’undefined’。然则结果输出是2。以下图所示:

《JavaScript变量提拔》

我们再来斟酌另一段代码,以下所示:

console.log(a);
var a = 2;

这段代码会输出什么样的结果呢?有些人可能会以为输出ReferenceError。由于变量a在没有声明的状况下就被使用了。实在结果呢,以下图所示:输出的是undefined

《JavaScript变量提拔》

为何会如许呢?这就牵出了本文的主题:JavaScript声明提拔

JavaScript代码的运转划定规矩

在JavaScript代码运转之前实际上是有一个编译阶段的。编译以后才是从上到下,一行一行诠释实行。变量提拔就发作在编译阶段,它把变量和函数的声明提拔至作用域的顶端。(编译阶段的事情之一就是将变量与其作用域举行关联)。
所以关于代码var a =2;来讲,编译器看到的是两行代码var a; a = 2;第一个语句是声明语句,在编译阶段处置惩罚。第二个语句是赋值语句,在运转阶段处置惩罚。
那末我们再回过头来看看题目中涌现的代码:

a = 2;
var a;
console.log(a);

应当如许来处置惩罚:

var a;            //编译阶段
a = 2;            //运转阶段
console.log(a);   //运转阶段

所以这段代码的终究输出的结果是2

第二段代码:

console.log(a);
var a = 2;

应当如许来处置惩罚:

   var a;            //编译阶段
   console.log(a);   //运转阶段 
   a = 2;            //运转阶段

所以这段代码的终究输出结果是undefined

变量提拔须要注重两点:

  1. 提拔的部份只是变量声明,赋值语句和可实行的代码逻辑还保持在原地不动

  2. 提拔只是将变量声明提拔到变量地点的变量局限的顶端,并非提拔到全局局限,申明以下:

foo();
function foo(){
    console.log(a); //会输出undefined
    var a = "2";
}
//变量提拔以后的结果
function foo(){
    var a;
    console.log(a);
    a = "2";
}
foo();

函数声明会提拔,然则函数表达式就不了。看以下代码:

foo();
var foo = function bar(){    //这是一个函数表达式,不再是函数声明。
    console.log("bar");
}

处置惩罚方式以下:

var foo;    
foo();    //TypeError,由于还没有赋值
bar();    //bar不可以在全局局限内援用
foo = function bar(){            
    console.log("bar");
}    

函数是一等国民

变量声明和函数声明都邑获得变量提拔,但函数声明会最早获得提拔,然后是变量声明。
斟酌以下代码:

foo();    //输出的结果为1
var foo;
function foo(){
    console.log(1);
}
foo = function(){
    console.log(2);
}   

处置惩罚方式以下:

function foo(){
    console.log(1);
} 
foo();
foo = function(){
    console.log(2);
}   

注重var foo;由因而反复声明变量,所以被编译优化去掉。

末了再来讲明几种状况

关于函数声明来讲,假如定义了雷同的函数变量声明,后定义的声明会覆蓋掉先前的声明,看以下代码:

foo();    //输出3
function foo(){
    console.log(1);
}
var foo = function(){
    console.log(2);
}  
function foo(){
    console.log(3);
} 

JavaScript中是没有块级作用域的观点(ps:ES6中有改进了),看以下代码:

foo();    //输出结果为2
var a = true;
if(a){
    function foo(){
        console.log(1);
    }
}else{
    function foo(){
        console.log(2);
    }
}   

这段代码输出结果为2,if语句没有块级作用域的功用,所以函数声明都被提拔到全局作用域中,又由于定义了两个foo,厥后的定义覆蓋了前边的定义,所以输出结果为2。

    原文作者:852774731
    原文地址: https://segmentfault.com/a/1190000003913151
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞