栈堆内存
基本数据类型是存储在栈内存中的,引用数据类型是存储在堆内存中的
var a=1;
var obj={"name":"咸鱼"}
对于这两句代码,其实就是在内存中做了两件事:1.首先在栈内存中开辟了一块空间用来存放a的变量和值;2.在堆内存中开辟了一块空间用来存储obj的值,同时在将地址指向栈内存中的变量名obj
作用域链
var a = 1;
function fn(){
var b = 2;
function fn1(){
console.log(b);//2
console.log(a);//1
}
fn1();
}
fn();
1.var a=1;这个时候我们是在全局执行环境的,浏览器的全局环境就是window作用域,我们的window作用域中有a和fn;
2.当我们往下走到fn的时候,栈内存会开辟一块新的执行环境,此时fn的执行环境中我们有b和fn1;
3.当我们接着往下走到fn1的时候,这时栈内存同样会开辟一块新的执行环境,此时fn1的执行环境中是没有任何变量数据的,但是我们在fn1中输出a、b,我们都是可以读取到的;这是因为程序在读取变量的时候是从内到外的开始读的,是随着fn1开始往上一层一层的查找,是这样的执行顺序(fn1 -> fn -> window),如果找到window中还没有读取到变量,这时程序才会报错;
闭包
GC机制
在 Javascript 中,如果一个对象不再被引用,那么这个对象就会被 GC 回收,否则这个对象一直会保存在内存中。
闭包的优缺点
优点:
1.可以读取函数内部的变量
2.可以避免全局污染
缺点:
1.闭包会导致变量不会被垃圾回收机制所清除,会大量消耗内存;
2.不恰当的使用闭包可能会造成内存泄漏的问题;
闭包代码示例
function outer() {
var a = '123'
return function add(){
//在这里因为作用域的关系,add是能访问到outer的所有变量的,但是outer是访问不到add的变量;
//所以思路一转,把add的值作为结果return出来变通实现outer外部函数访问到了内部函数变量
// add就是一个闭包函数,因为他能够访问到outer函数的作用域,add中没有找到变量a,则会继续往上层作用域找
console.log(a);
}
}
var inner = outer() // 获得add闭包函数
inner() //"123"