前端 -- JS变量提升

448 阅读3分钟

1、变量提升

在JS代码执行之前,会先把代码从上到下浏览器一遍,然后把带有var 和function的提前声明

  • var的只声明,不定义(就像只知道有个人,但是不知道是谁)
  • function的不仅声明,还定义(即会把函数体当作字符串放在堆内存中)

2、作用域(栈内存)

全局作用域不能拿到私有作用域的变量,但是私有作用域可以拿全局作用域的变量;

  • 全局作用域
  • 私有作用域
    • 函数执行形成的作用域
    • ES6中新增的块级作用域(如果把let和const放在if、while、for的{}内,那么他们定义的变量就是这个{}内的私有变量,在{}外不可以访问)

3、JS的运行

1、代码怎么执行
第一步:首先进行语法检测,(如果有问题就不再向下进行,因为JS是单线程,从上向下执行,只有代码报错,就不向下执行了)如果没有问题,就进行下一步
第二步:进行变量提升(声),将带有var 和function 的声明出来放在栈内存的变量存储区,并且把带有function的定义一下(即把函数体放在自己重新开辟的堆内存中);
第三步:代码执行,此时执行的时候遇到var a = 12,就是直接去给在变量提升阶段出来的a赋值;遇到function fn(){}时不要再操作;当遇到fn()执行这个函数的时候,再去开辟一个私有的栈内存进行函数的执行;

4、var 和 let的区别

1、在全局作用域下,var 和function声明的变量会给Window增加键值对,属性名是变量名,属性值是变量的值;
2、var 和function可以创建重复的变量,但是let 和const不可以,并且const定义的时候需要赋值,不赋值会报错,而let不赋值是undefined;
3、不管之前通过什么办法声明了一个变量,只要当前栈内存中存在了这个变量,使用let/const等再声明都是语法报错
4、var 和function 有变量提升,但是let 和 const 没有

let a = 12;
let a = 12;
//报错,因为let不允许重复声明一个变量
var a = 12;
let a = 12;
//会报错,因为第一步对var变量提升,此时已经声明a,浏览器中已经知道有a这个变量了,因此再使用let这个变量名就不可以了(依旧满足let不允许重复声明的机制)。
let a = 12;
var a = 12;
//报错;这种情况和第二种一样
b = 12;  //给Window增加键值对
var b = 12; //不仅给window增加键值对,还会创建全局变量b
let b = 12; //

5、作用域链

  • 变量的查找机制:在某个作用域中要使用一个变量,先看这个变量是不是自己私有的,不是私有变量则去上级作用域查找(指的是该函数是在哪个作用域形成的,那么上级作用域就是那个作用域);
  • 只有在自己的作用域里面定义的(变量提升出来),就是私有的,不能再去上级查找;

6、函数在变量提升阶段干了什么?

定义函数名,并且把函数体的内容以字符串的方式存储在新开辟的堆内存中,函数名关联的是堆内存的地址。等后期调用函数的时候,函数体内的内容才去执行;

7、函数在执行的时候经历那几步

  • 开辟一个新的私有栈内存;
  • 形参赋值
  • 变量提升
  • 代码运行
  • 作用域是否被销毁

8、例题