变量提升
栈内存:作用域
- 提供一个供JS代码自上而下执行的环境(代码都是在栈中执行的)
- 由于基本数据类型值比较简单,他们都是直接在栈内存中开辟一个位置,把值直接存储进去的
当栈内存被销毁,存储的哪些基本值也都跟着销毁了
堆内存:引用值对应的空间
- 存储引用类型值的(对象:键值对 函数:代码字符串)
- 当前堆内存释放销毁,那么这个引用至彻底没了
- 堆内存的释放:当堆内存没有被任何的变量或者其他东西所占用,浏览器会在空闲的时候,自主的进行内存回收,把所有不被占用堆的内存销毁掉(谷歌浏览器)
xxx = null 通过空对象指针null可以让原始变量(或者其他东西)谁都不指向,那么原有被占用的堆内存就没有被东西占用,浏览器会销毁他
当栈内存(作用域)形成,JS代码自上而下执行之前,
浏览器首先会把所有带“var”/“function”关键字的进行提前的声明或者定义
这种预先处理机制称之为“变量提升”
- 声明(declare):var a / function sum (undefined)
- 定义(defined):a = 12 (定义其实就是赋值操作)
[变量提升阶段]
带"var"的只声明未定义
带"function"的声明和赋值都完成了
变量提升只发生在当前作用域(例如:开始加载页面的时候只对全局作用域下的进行提升,因为此时函数中存储的都是字符串而已)
在全局作用域下声明的函数或者变量是“全局变量”,同理,在私有作用域下声明的变量是“私有变量” [带var/function的才是声明]
创建函数部分代码后,直接跳过即可(因为在提升阶段就已经完成函数的赋值操作了)
console.log(a);
var a = 12;
带var和不带var的区别
在全局作用域下声明一个变量,也相当于给window全局对象设置了一个属性,变量的值就是属性值(私有作用域中的声明的私有变量和window没啥关系)
console.log(a);// undefined
console.log(window.a) // undefined
console.log('a' in window) // true 在变量提升阶段,在全局作用域中声明了一个变量A,此时就已经把a当做属性赋值给window了,只不过此时还没有给a赋值,默认值undefined :in 检查某个属性是否隶属于这个对象
var a = 12; // 全局变量值修改,win的属性值也跟着修改
console.log(a); // 12
// 全局变量和win中的属性存在“映射机制”
// 不加var的本质是win的属性
console.log(a) // VM60:1 Uncaught ReferenceError: a is not defined
console.log(window.a) // undefined
console.log('a' in window) // false
a = 12; // window.a = 12
console.log(a); // 12
console.log(window.a) // 12
var a = 12,
b = 13;
// b 带var
var a = b = 12;
// b不带var 相当于var a = 12; b = 12;
私有作用域带var和不带var的区别
- 带var的在私有作用域变量提升阶段,都声明为私有变量,和外界没有任何关系
- 不带var不是私有变量,会向上级作用域查找,看是否为上级的变量,不是,继续向上查找,一直找到window为止(我们把这种查找机制叫做:“作用域链”)也就是我们在私有作用域中操作的这个非私有变量,是一直操作别人的