原则
变量提升分为两种:
- 使用
var
声明的变量,比如var a = 10
- 使用
function
声明的函数,比如function foo() {}
有几点需要注意以下:
- 使用
var
声明的变量要比使用function
声明的函数 优先提升 - 全局变量不会得到提升,比如
a = 10
这种
Have A Try
下面祭出 3 道题:
题目 1
function foo() {
console.log(1)
}
foo()
function foo() {
console.log(2)
}
foo()
答案与解析
答案 : 2 2
解析 :
两个 foo 函数都被提升,
但是第二个 foo 函数会把 第一个 foo 函数覆盖,
所以两次对于 foo 函数的调用结果都是 2
题目 2
var foo = function () {
console.log(1)
}
foo()
function foo() {
console.log(2)
}
foo()
答案与解析
答案 : 1 1 解析 : 通过 var 声明的变量 和 通过 function 声明的函数都会得到提升 但是前者的优先级要比后者高会先被提升 以此题为例,以下为提升后的代码 var foo function foo() { console.log(2) } foo = function () { console.log(1) } foo() // 1 foo() // 1
题目 3
function fn() {
console.log(typeof foo)
var foo = 'this is variable'
function foo() {
return 'this is function'
}
console.log(typeof foo)
}
fn()
答案与解析
答案 : function string 解析 : 以下为提升后的代码 var foo = undefined // 变量 foo 先被提升 function foo() { // 函数 foo 后被提升,并把变量 foo 覆盖 return 'this is function' } console.log(typeof foo) // function foo = 'this is variable' // 给 foo 重新赋值 console.log(typeof foo) // string
题目 4
function foo(a, b) {
console.log(a, b)
var b = 3
function b() {}
var a = function () {}
console.log(a, b)
}
foo(1, 2)
答案与解析
答案 : 1 [Function: b] [Function: a] 3 解析 : 遇到此题你会发现之前的规则并不适用了 所以需要使用执行上下文中的 VO 去解释 当 foo 函数被调用的时候 VO 首先会找到行参和 arugments,即 VO = { arguments, a: 1, b: 2 } 然后 VO 会找 var 声明的变量并设置为 undefined 但是这里有个例外是 var 声明的变量如果和形参产生冲突,那么直接忽略 所以此时 VO 不变,还是 VO = { arguments, a: 1, b: 2 } 紧接着 VO 会去找到字面量 function 声明的函数 这里如果与行参产生冲突则直接覆盖行参,所以此时 VO 为 VO = { arguments, a: 1, b: function(){} } 到这里第一个 console.log 的值就显而易见了 1 [Function: b] 接下来 b 和 a 分别被赋值,那么此时 VO 是 VO = { arguments, a: function, b: 3 } 到这里第二个 console.log 的值也就呼之欲出了 [Function: a] 3