JavaScript 提升

  • 包括变量和函数在内的所有声明都会在任何代码被执行前先被处理。

  • 原因:引擎会在解释JavaScript代码之前首先对其进行编译,编译阶段包括找到所有声明并用合适的作用域将它们关联起来,这也是词法作用域的核心内容。

  • 注:只有声明本身会被提升,而赋值或其他运行逻辑会留在执行阶段

一、var变量声明提升
  • 示例代码如下:
        a=2;
        var a;//提升
        console.log(a);//2
        
        console.log(b);//undefined
        var b=2;//只提升了var b;
var b = 2;是被JavaScript看作是两个声明:var b;和 b=2;
  • 第一个是定义声明 var b;是在编译阶段进行的
  • 第二个是赋值声明 b = 2;是在执行阶段进行的
二、函数声明提升

函数声明会被提升,函数表达式不会被提升

    foo1();//函数声明被提升,可以正常调用
    function foo1() {
        console.log(a);//undefined
        var a=2;
        console.log('foo1调用成功');
    }
    //每个作用域都有提升操作

    foo2();//TypeError
    bar();//ReferenceError
    var foo2=function bar() {
        console.log('调用成功');
    }
  • 这里的foo2()被提升并分配给所在作用域,因此不会导致ReferenceError
  • 但foo此时并没有赋值,所以 foo() 是对undefined值进行函数调用,因此抛出TypeError异常
  • 即便是具名的函数表达式,名称标识符在赋值之前也无法在所在作用域中使用
上述的foo2代码块经过提升后,实际上会被理解为以下形式
    var foo2
    foo2();//TypeError
    bar();//ReferenceError
    foo2=function bar() {
        var bar=...
        console.log('调用成功');
    }
三、函数优先

函数声明会首先被提升,然后才是变量声明提升。

    foo();//1
    //函数声明会被提升到普通变量之前
    //所以var foo被当作foo的重复声明忽略掉了
    var foo;
    function foo() {
        console.log(1);
    }
    foo=function () {
        console.log(2);
    }
    //输出的是1,该代码片段被引擎理解如下
    function foo() {
        console.log(1);
    }
    foo();//1
    foo=function () {
        console.log(2);
    }

出现在后面的函数声明可以覆盖前面的

    foo();//3
    var foo;
    function foo() {
        console.log(1);
    }
    foo=function () {
        console.log(2);
    }
    function foo() {
        console.log(3);
    }
四、小结
  • 要var普通声明和函数声明混合用时要注意,
  • 要避免重复声明。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。