几分钟掌握JavaScript预解析的那些坑

JavaScript预解析

1Q:未声明变量,直接输出会出现什么结果?

console.log(num);

1A:报错:变量未被定义。

Uncaught ReferenceError: num is not defined

2Q:在输出变量后才声明并赋值变量会出现什么结果?1

console.log(num);
var num = 10;

2A:显示undefined

undefined

3Q:先调用函数,再定义函数会出现什么结果?2

fn();
function fn() {
    console.log('Javier_Ji');
}

3A:正常显示。

Javier_Ji

4Q:先调用函数,再声明函数表达式会出现什么结果?3

fn();
var fn = function() {
    console.log('Javier_Ji');
}

4A:错误:fn不是函数。

Uncaught TypeError: fn is not a function

解释

  1. JavaScript代码是由浏览器中的JavaScript解析器来执行的。JavaScript解析器在运行JavaScript代码的时候分为两步:
    • 预解析:js引擎会把js里面的所有的var以及function提升到当前作用域的最前面。
    • 代码执行:按照代码书写的顺序从上往下执行。
  2. 预解析分为:变量预解析(变量提升)和函数预解析(函数提升)
    • 变量提升:把所有的变量声明提升到当前的作用域最前面,不提升赋值操作。
    • 函数提升:把所有的函数声明提升到当前的作用域最前面,不调用函数。

示例

下面的代码执行后会得到什么结果?4

fn();
console.log(c);
console.log(b);
console.log(a);

function fn() {
    var a = b = c = 9;
    console.log(a);
    console.log(b);
    console.log(c);
}

执行后结果如下:

9
9
9
9
9
Uncaught ReferenceError: a is not defined

  1. 针对2Q的解答
    先预解析,相当于执行了如下代码:

    var num;			//把变量声明提升到当前作用域(本例中是全局)最前面
    console.log(num);	//执行后续的代码
    num = 10;			//赋值
    
    ↩︎
  2. 针对3Q的解答
    先预解析,相当于执行了如下代码:

    function() {
        console.log('Javier_Ji');
    }				//把函数声明提升到当前作用域(本例中是全局)最前面
    fn();			//执行后续的代码,函数被正常调用
    
    ↩︎
  3. 针对4Q的解答
    先预解析,相当于执行了如下代码:

    var fn;			//把var声明提升到当前作用域(本例中是全局)最前面
    fn();			//执行后续的代码,由于函数还没被定义,且var fn;语句定义的是变量,则会报错,fn不是函数
    function() {
        console.log('Javier_Ji');
    }				//执行后续的代码
    
    ↩︎
  4. 针对示例的解答
    先预解析,相当于执行了如下代码:

    function fn() {
        var a;				
        a = b = c = 9;
        console.log(a);
        console.log(b);
        console.log(c);
    }
    fn();
    console.log(c);
    console.log(b);
    console.log(a);
    

           本例中的代码var a = b = c = 9;相当于先在函数内部定义变量var a,之后赋值a = b = c = 9,由此可得,变量a的作用域是在fn函数内部,而bc相当于定义了一个全局变量。 ↩︎

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章