变量提升与函数提升
变量提升
定义: var声明的变量,js在运行时会将其声明提升到它所在作用域的顶端去执行,到我们代码所在的位置来赋值。
- 变量提升只提升声明,不提升赋值(初始化)。
console.log(a);//undefinded,因为一开始执行了var a
var a = 123
- 变量提升只提升到它所在的作用域,并不一定是全局
console.log(v1);//undefined
var v1 = 100;
function func() {
console.log(v1);//undefined,函数作用域中的v1提升
var v1 = 200;
console.log(v1);//200
}
func();
console.log(v1);//100
- 在js中只有两种作用域,全局作用域和函数作用域,在ES6之前,js没有块级作用域。若变量在函数中声明,则会提升会提升到它所在的函数的顶端,而不是所在的大括号(块级作用域)的顶端(现在你应该明白下面的输出为什么是
1而不是undefined了):
function fun1() {
var a = 1;
{
console.log(a);//1,第二行的a依然可以被括号内读取
var a = 2;
}
console.log(a);//2,第五行的a依然可以影响到括号外的输出
}
fun1();
函数提升
函数也有提升现象,并且有一些需要注意的点
定义:对于声明式函数,js在运行时会将函数的整个代码块提升到它所在的作用域的最开始执行。
- 声明式函数会被提升,字面量式函数(函数表达式)不会被提升
//函数声明式
function func () {}
//函数字面量式
var a = function () {}
- 函数的提升优先级高于变量的提升,即函数优先原则。
- 下面的代码中
func的函数声明优先于变量声明,所以当函数和变量同名时,变量的声明会被暂时屏蔽(第三行打印出来的func是一个函数),直到该名称被重新赋值(第11行的func已经变成一个变量,不再是一个函数)
- 下面的代码中
func();//1
var func;
console.log(func); // func是函数,并且里面是1
function func() {
console.log(1);
}
func = function(){
console.log(2);
}
func();//2,此时的func依然是函数,但是值已经改变
func = 2;
console.log(func); // 2,func不再是函数
func();//Uncaught TypeError func is not a function
- 高版本的浏览器中,在块级作用域内部声明的函数将不会被提升
foo();
//低版本:2 猜测因为两次声明同一个函数,后声明的会替换先声明的(注意同名函数可以覆盖函数的声明,但是同名变量无论如何也不能覆盖函数的声明,因为函数优先)
//高版本: Uncaught TypeError: foo is not a function
var a = true;
if(a){
function foo () { console.log(1); }
}else{
function foo () { console.log(2); }
}
变量和函数提升背后的原理
我们习惯将var a = 2看做是一个声明步骤,而实际上js引擎并不这么认为。它将var a和a = 2看做两个单独的步骤,第一个是编译阶段的任务,而第二个则是执行阶段的任务
这意味着无论作用域中的声明出现在什么地方,都将在代码本身被执行前首先进行处理,可以将这个过程形象地想象成所有的声明(变量和函数)都会被“移动”到各自作用域的最顶端,这个过程被称为提升
参考资料
https://blog.csdn.net/qq_39712029/article/details/80951958
https://blog.csdn.net/qq_33505829/article/details/86158287?depth_1-utm_source=distribute.pc_relevant.none-task&utm_source=distribute.pc_relevant.none-task

浙公网安备 33010602011771号