js中的变量提升(仅限var,let和const不提升)

91 阅读3分钟

1. js代码的执行顺序

引擎在解释JS代码之前首先要对代码进行编译,在编译阶段中有一部分工作就是找到所有的声明,并用合适的作用域将他们关联起来。

所以总结来说,包括变量和函数在内的所有声明在编译阶段都会首先被处理,然后才是代码被执行的阶段

而且每个作用域都会进行提升(函数内部会进行提升)

啥都没写(前后都没有var)则是Windows=>全局

2. 变量提升

a = 'haha'
var a
console.log(a) //a=haha
===============================
console.log(a)//a=undefined
var a = 'haha'
===============================
var a=123//编译过程先进行var a声明,之后执行阶段进行赋值。

面试题

console.log(v1);
var v1 = 100;
function foo() {
    console.log(v1);
    var v1 = 200;
    console.log(v1);
}
foo();
console.log(v1);
编译过程=================
var v1;
function foo() {
    console.log(v1);
    var v1 = 200;
    console.log(v1);
}
执行过程===============
console.log(v1);//1.输出undefined
v1=100;
foo();//在执行foo过程中,在函数内部也要进行提升,2.输出undefined
      //之候v1在函数内部被赋值200;3.输出200    
console.log(v1); //4.输出100

3. 函数提升

javascript中不仅仅是变量声明有提升的现象,函数的声明也是一样;具名函数的声明有两种方式:

    a. 函数声明式    b. 函数字面量式

//函数声明式,整体函数包括大括号一起提升
function bar () {}
//函数字面量式 ,提升之后只提升声明: var foo
var foo = function () {}

//函数声明式,整体函数包括大括号一起提升

function bar () {}

//函数字面量式 ,提升之后只提升声明: var foo

var foo = function () {}**

函数字面量式的声明和变量提升的结果是一样的,函数只是一个具体的值; 但是函数声明式的提升现象和变量提升略有不同

console.log(bar);
function bar () {
  console.log(1);
}
//打印结果:ƒ bar () {
//  console.log(1);
//}
//bar并没有被执行,所以不打印1
执行顺序================================
function bar () {
  console.log(1);
}
console.log(bar);

我们使用的是函数声明的方式,所以js会有类似于变量提升的函数提升,与变量提升不同,函数提升不仅仅提升函数声明,而是提升函数整体

function chifan(){
  console.log('我要吃米饭')
}
chifan()
function chifan(){
  console.log('我要吃面')
}
chifan()
//编译执行=============================
var chifan=function (){
  console.log('我要吃米饭')
}
var chifan=function (){
  console.log('我要吃面')
}
chifan()//吃面
chifan()//吃面
===================================================
我们可以看到,函数提升不仅仅把声明做了提升,同时还把赋值跟着声明一起提升到了最前面
再来看下面这个例子
================================
var game=function (){
  console.log('玩英雄联盟')
}
game()
var game=function (){
  console.log('玩CSGO')
}
game()
//编译执行==========================
var game
var game
game=function (){
  console.log('玩英雄联盟')
}
game()
game=function (){
  console.log('玩CSGO')
}
game()
//结果
'玩英雄联盟'
'玩CSGO'

4.特殊情况

console.log(drink)
function drink(){
  console.log('酒')
}
var drink='饮料'

这里我们可以看到drink即是函数声明的函数,又在最后赋值了一次,这样去执行时,如果变量名称跟已经声明的形式参数或函数相同,则变量声明不会干扰已经存在的这类属性,具体编译过程如下:

function drink(){
  console.log('酒')
}
console.log(drink)
var drink='饮料'
//结果

** !!! ~~这里运行结果是重复声明但是 ~~这个链接里给出有结果~~~~