搞懂JS作用域链和闭包

作用域链

每个对象都有一个隐藏属性[[scope]],存放它自身的作用域链,

  • GO:全局执行上下文
  • AO:函数执行上下文
function test1() {
  function test2() {
    var b = 2;
  }
  var a = 1;
  test2();
}
var c = 3;
test1();
  1. window 是全局作用域,它的 GO 上有 test1 和 c,它的 scope 上只有 GO

  2. 当 test1()开始执行,就产生了 test1 的 AO,AO 上有 test2 和 a,test1 的 scope 上有自己的 AO 和 window 的 GO,并且会自己的 AO 后占据 GO 的位置,GO 向后排

  3. 当 test2()开始执行,产生了 test2 的 AO,AO 上有 b,test2 的 scope 上会有自己的 AO,test1 的 AO,全局的 GO。
    并且会把自己的 AO 放在第一位,test1 的 AO 和全局 GO 依次向后排

为什么外部作用域不能访问更小的作用域???

链式结构生成:局部作用域越靠内部。自己的 scope 上会有更多的上级 AO(GO 每个作用域都会有),当我们访问变量时,作用域会在 scope 上从自己的 AO 找,如果找不到则向下挨个寻找,直到查询到全局 GO 位置,外部的作用域的 scope 上根本没有更小作用域的 AO,所以每一层的作用域只能访问向上层次的作用域。

闭包

那么问题来了,我要怎么访问局部作用域呢?

function test1() {
  function test2() {
    var b = 2;
    console.log(a);
  }
  var a = 1;
  return test2;
}
var c = 3;
var test3 = test1();
test3();
  • 正常执行过程中,当函数执行完毕后,浏览器的内存空间将销毁函数所占用的内存
  • 在test1执行中用return返回test2
  • 等于是将test2赋给了全局的test3,也就意味着test2可以通过test3执行而执行,test2中的console.log(a),使用了test1中的变量,就会告诉浏览器a我在用,test1执行完毕后不能把a销毁
  • 至此,我们在外部拿到了test1作用域中的a。这就完成了闭包的过程

提示

当内部函数被返回到外部并保存时,一定会产生闭包,闭包会导致原来的作用域链不释放。过度使用闭包可能会导致内存泄漏或加载速度过慢

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值