Javascript 变量提升杂谈

引言

直觉上 JavaScript 代码在执行时是由上到下一行一行执行的,但实际上这并不完全正确,考虑以下代码:

// 示例一
a = 2
var a
console.log(a) // 2

// 示例二
console.log(a) // undefined
var a = 2

有人会认为示例一申明在后,a 会重新赋值为默认值 undefined;而示例二由于变量 a 在使用前没有先进行声明,
因此会抛出 ReferenceError 异常。但是结果令人意外,这里涉及到一个知识点,即变量提升

编译器的工作

引擎会在解释 JavaScript 代码之前首先对其进行编译,编译过程中包括变量和函数在内的所有声明都会在任何代码被执行前首先被处理

所以上面示例一的代码片段会以如下形式进行处理:

var a
a = 2
console.log(a)

类似的,示例二的代码片段会以如下形式进行处理:

var a
console.log(a) // a 被提升,在调用前并未赋值,所以是 undefined
a = 2

需要注意的是函数声明会被提升,函数表达式则不能,考虑下面的代码:

foo()

function foo () {
  console.log(a) // undefined
  var a = 2
}

上面的 foo 是一个函数申明,函数内部的 a 也被提升到函数内部的上方,再考虑下面的代码:

foo() // TypeError

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

上面的 foo 是一个函数表达式,虽然 foo 被提升了,但是 foo 此时并没有赋值,foo() 由于对 undefined 值进行函数调用而导致非法操作,
因此抛出 TypeError 异常

函数优先

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

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

结果会输出 1,var foo 因为是重复的声明因此被忽略了

let 和 const 不可提升

// 示例一
a = 2
let a // Uncaught SyntaxError
console.log(a)

// 示例二
a = 2
const a // Uncaught SyntaxError
console.log(a)

let 和 const 是 ES6 中的关键字,因为语法原因,let 和 const 不能像 var 申明 那样实现变量提升的效果,上面两个示例都会报错

除特殊说明外本人博客均属原创,转载请注明出处:http://blog.johnhan.cn/blog_1071.html
京ICP备19044523号-1