作用域和作用域链
概念:在JavaScript里,函数、块、模块都可以形成作用域(一个存放变量的独立空间),他们之间可以相互嵌套,作用域之间会形成引用关系,这条链叫做作用域链。作用域分为静态作用域和动态作用域,作用域链分为静态作用域链和动态作用域链。JS语言是静态作用域,JS的作用域链是静态作用域链。
- 静态作用域: 函数被定义的那一刻,函数中变量的查找范围就确定了,取决于函数的定义位置。可以静态分析出整条作用域链中的变量关系。 -- 可以延伸到闭包、GC垃圾回收(标记清除)
- 动态作用域: 函数被执行时,函数中变量的查找范围才确定,取决于函数的执行位置。缺点是不直观,无法静态分析。
闭包
闭包是可以访问其它函数内部变量的函数 闭包的设计是为了解决子函数晚于父函数销毁的问题,js会在父函数销毁时,把子函数引用到的变量打包成Closure包放到函数的[Scopes]上,让它即使父函数销毁了也随时随地能访问外部环境。
var x = 1;
var obj = {x:2}
obj.fn=(function(x){
this.x*=x++;
return function(y){
x+=y;
this.x*=++x;
console.log(x);
}
})(obj.x);
var fn = obj.fn;
obj.fn(2);//6
fn(1);//8
console.log(obj.x,x);//false:24 8 true: 12 16闭包的优点
- 可以保存变量,用于缓存
- 避免全局变量污染
- 加强封装性 让js也能支持私有变量
闭包的缺点
- 大量使用时 内存消耗大 影响性能
- 过度使用时 可能会导致内存泄漏 或程序卡慢等 所以在退出函数之前应删除不使用的局部变量
闭包的应用
- 私有变量
- 回调计数器
- 柯里化函数、compose函数等高阶函数
- 防抖、节流
- 独立作用域、类库包装等
除闭包外还有哪些会导致内存泄漏
- 意外的全局变量 (隐式全局变量)
- 定时器
- 脱离文档的DOM引用 引用了一个dom元素 元素被删除后 引用变量还存在
- 未销毁的交叉观察对象Intersection API
如何检测内存泄漏
- 内存泄漏通常是由于闭包引起的
- 可用的检测手段: chrome devtool的Memory面板