目录
一、什么是预解析
预解析是指在当前作用域下,
JavaScript
代码执行之前,浏览器会默认把带有
var
和
function
声
明的变量在内存中进行提前声明或者定义。
示例:
<script>
a = 2;
var a;
console.log(a);//2
</script>
二、预解析
2.1、变量预解析
变量预解析也叫变量提升,是指变量的声明会被提升到当前作用域的最上面,但变量的赋值不会提升。
示例1:
<script>
console.log(age); // undefined
var age = 18;
</script>
上面代码执行后会输出
undefined
而不是报错,为什么?
这就是变量预解析引起的。
预解析后:
示例2:
预解析后:
2.2、函数预解析
函数预解析也叫函数提升,是指函数的声明会被提升到当前作用域的最上面,但是不会调用函数。
示例1:
示例1函数预解析过程:
示例2:
示例2函数预解析过程:
注意:如果使用函数表达式方式声明的函数,则不会被提升。
三、声明注意事项
(1)变量声明和函数声明时,变量的声明提升优先于函数的声明提升。但是,函数的声明会覆盖未定义的同名的变量。
示例:
预解析过程:
(2)变量声明和函数声明时,变量的声明提升优先于函数的声明提升。如果变量有值,则不会被覆盖。
示例:
预解析过程:
(3)后面的函数声明会覆盖前面的函数声明
<script>
function fn() {
console.log('hello');
}
function fn() {
console.log('world');
}
fn(); //world
</script>
总结:在声明时(不管是变量还是函数)都尽量不要取相同的标识符(名称)。
四、变量提升原因
在编译阶段,引擎会声明变量和函数,但不会对变量进行赋值,这主要是出于对性能的考虑。变量被声明,但是不一定会在后面使用到,如果没有使用却赋了值,只是白白浪费内存而已。简单说,var a
这段代码发生在编译阶段,而
=1
这段代码会根据实际情况,发生在执行阶段,这也就是"
变量提升
"
的原因。另外需要注意的是,函数声明的是整个函数体(
因为函数声明不存在赋值操作
)
,而且优先级高于同名的变量。
示例:
<script>
console.log(fn()); //输出:1 \
console.log(n); //输出:undefined
function fn() {
return 1;
}
var n = 2;
</script>
在浏览中预解析为如下:
<script>
var a;
function fn() {
return 1;
}
console.log(fn());
console.log(n);
n = 2;
</script>