JavaScript_变量提升、函数提升
变量提升、函数提升
发生原因:在js代码执行前引擎会先进行预编译,预编译期间会将变量声明与函数声明提升至其对应作用域的最顶端。
注意:
- var,function,function*的声明会在提升时进行初始化赋值为 undefined,访问这些变量的时候,不会报 ReferenceError 异常,
- 而使用 let,const,class 声明的变量,被提升后不会被初始化,这些变量所处的状态被称为“temporal dead zone”,此时如果访问这些变量会抛出ReferenceError 异常,看上去就像没被提升一样。
- 只有声明的变量和函数才会进行提升,隐式全局变量不会提升。
(声明 let a; / var a; 隐式全局变量:b = ‘abc’)
提升过程
变量提升
- 变量在声明提升的时候,是全部提升到作用域的最前面,一个接着一个的。
- 但是在变量赋值的时候就不是一个接着一个赋值了,而是赋值的位置在变量原本定义的位置。
- 原本js定义变量的地方,在js运行到这里的时候,才会进行赋值操作,而没有运行到的变量,不会进行赋值操作。
注意:在ES6出来之前,JS并没有块级作用域这一说,只有全局作用域和局部作用域。变量提升指的是使用var声明的变量提升到他所在的作用域的最顶端。
console.log(example);//undefined
var example = 12;
console.log(example);//12
js在解析上面的代码的时候,其实会按照下面的方式进行解析的:
var example;
console.log(example);//undefined
example = 12;
console.log(example);//12
函数提升
函数的提升是直接将整个函数整体提升到作用域的最开始位置,相当于剪切过去的样子。
注意:函数提升只针对具名函数,而对于赋值的匿名函数,并不会存在函数提升。
console.log(example_a); //[Function: example_a]
console.log(example_b); //undefined
function example_a(){
console.log('hello')
}
var example_b=function(){
console.log('world')
}
console.log(example_b); //[Function: example_b]
js在解析上面的代码的时候,其实会按照下面的方式进行解析的:
function example_a(){
console.log('hello')
}
console.log(example_a); //[Function: example_a]
console.log(example_b); //undefined
var example_b=function(){
console.log('world')
}
console.log(example_b); //[Function: example_b]
优先级
函数提升优先级高于变量提升,且不会被同名变量声明覆盖,但是会被变量赋值后覆盖。而且存在同名函数与同名变量时,优先执行函数。
console.log(example)//[Function: example]
function example() {
console.log(123)
}
var example = 'abcd'
console.log(example)//abcd
console.log(example())//example not a function
js在解析上面的代码的时候,其实会按照下面的方式进行解析的:
function example() {
console.log(123)
}
var example;
console.log(example)//[Function: example]
//example函数未被example变量覆盖
//存在example函数和example变量 优先执行example函数
example = 'abcd'
console.log(example)//abcd
console.log(example())//example not a function
//example变量进行赋值,example函数被覆盖
console.log(example())打印undefined
原因
一个函数的函数体为空时,在打印它的调用时,打印出 undefined
console.log(example)//[Function: example]
console.log(example())
//123
//undefined
function example() {
console.log(123)
}
var example = 'abcd'
console.log(example)//abcd