【JS基础】浅谈变量提升和函数提升

393 阅读3分钟

变量提升是啥

JavaScript中存在一种叫做变量提升的东西,那么这种东西是什么呢?不多说,我们先来看一段代码

console.log(a);
var a = 2; 

大家可以调出F12去跑一下,发现输出了undefined,这是为啥嘞,明明我们是先调用后声明呀。但是这个其实是因为Js中存在变量提升现象,所以在运行这段代码的时候,他的处理方式是这个样子的:

var a;
console.log(a);
a = 2;

剖析下底层发现编译器会先找到所有声明的变量,并将他与当前的作用域关联起来,然后Js引擎会在后期再给他赋值。所以你可以认为会存在一个类似于预注册的情况,先将变量“预注册”却没有赋值。

顺带一提:变量提升是将变量“预注册”到当前作用域的顶部

console.log(a); //报错,ReferenceError

function test(){
  console.log(a);
  var a = 2;
}

顺带二提:es6使用let和const声明变量不会出现变量提升

console.log(b);//报错,ReferenceError
const b = 2; 
console.log(c);//报错,ReferenceError
const c = 2; 

函数提升是啥

说完了声明变量,我们还要来说说声明函数的情况,这个还是存在一定的区别的,但是我们首先来了解一下声明函数的方式。

函数声明和函数表达式

函数声明和函数表达式是两种不同的声明函数的方式,我们继续看代码

//函数声明
function test(){
    ...//doSth
}

//函数表达式
var test = function(){
    ...//doSth
}

可以看到,函数表达式就是一条式子,函数声明则简单粗暴直接命名函数。

函数声明和函数表达式的区别

简单的一句概括就是,函数声明会提升而函数表达表达式不会提升,直接上代码

console.log(test1()) // 'this is test1'
function test1(){
  return 'this is test1';
}

console.log(test2) // undefined
var test2 = function(){
  return 'this is test2'
}

我们可以看到函数声明的函数存在了函数提升,这是因为函数声明的时候函数体也提升了,而函数表达式只是将test2这个变量名提升,如果我们直接运行,他并不会报出ReferenceError而是出现了TypeError

变量提升和函数提升的比较

有趣的是,虽然变量和函数在声明时都存在提升,但是其实运行过程中我们发现,函数提升会优先于变量提升,继续看代码:

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

以上代码在运行是其实是这样的

function foo(){
  console.log(1);
}
foo();//1 
}

var foo = 2会因为重复声明而被忽略掉,因此结果输出1。

顺带一提:后面的函数声明会覆盖前面的函数声明

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

到此,浅谈结束,不知道有没有漏谈或者模糊出错的知识点,欢迎各位在评论中补充。谢谢阅读。