05 JS 声明提升

关于编译器,引擎会在解释 JS 代码之前首先对其进行编译。编译阶段的一部分工作就是找到所有的声明,并用合适的作用域将它们关联起来。

1.声明提升

“提升”就是变量和函数声明从它们在代码中出现的位置被“移动”到了最上面,这个过程就叫“提升”。

// 代码示例 1
foo();
function foo() {
    console.log(a); // undefined
    var a = 2;
}

如上面代码示例 1, foo 函数的声明被提升了,因此第一行中的调用可以正常执行。需要注意的是,每个作用域都会进行提升操作。也就是函数自身也会在内部对 var a 进行提升,所以最终的形式可以理解为如下代码示例 2:

// 代码示例 2
function foo() {
    var a;
    console.log(a); // undefined
    a = 2;
}
foo();

2.函数表达式不会被提升

// 代码示例 3
foo(); // TypeError 类型错误

var foo = function bar() {
     // ...
}

foo() 由于对 undefined 值进行函数调用而导致非法操作,因此抛 TypeError 出异常。

3.函数优先

函数声明会被提升到普陀变量之前。

// 代码示例 4
foo(); // 1

var foo;

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

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

上述代码示例 4 会被引擎理解为如下形式:

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

foo();  // 1

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

重复的函数声明可以覆盖前面的

尽可能避免在块内部声明函数

总结

  • var a = 2; 其中 var a; 是编译阶段的任务,a = 2; 是执行阶段的任务;
  • 所有的声明(变量和函数)都会被“移动”到各自作用域的最顶端,这个过程叫“提升”;
  • 声明本身会被提升,而包含函数表达式在内的赋值操作不会被提升;
  • 避免重复声明。

注:文章参考总结自 《你不知道的 JavaScript 上卷》[美] KYLE SIMPSON 著 第 42 页。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容