Skip to content

作用域和作用域链

概念:在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面板