• 作用域和作用域链


    1.作用域概念

    • 作用域可以理解为执行环境中变量或函数的作用范围
    • 定义了该范围内变量或函数是否有权访问到其他数据
    • 作用域都有一个变量对象
    • 包括全局作用域、局部作用域、ES6中的块级作用域

    2.全局作用域

    1. 全局作用域页面打开时被创建,页面关闭时被销毁
    2. 写在script标签中的变量和函数作用域为全局,在页面任意位置都可访问
    3. 全局作用域可以认为就是window,因为所有的全局变量和函数都是通过window对象的属性和方法创建的

    3.局部(函数)作用域

    函数调用时,局部作用域被创建,函数执行完毕,局部作用域被销毁

    函数多次被调用每次都会重新创建一个新的独立函数作用域

    函数作用域可以访问上层作用域,但是相邻函数作用域是独立的

    4.ES6中的作用域

    ES6以前没有块级作用域

    ES6中的块级作用域:通过let和const进行声明,和其他作用域一样,对外不可见

    5.作用域链

    作用域链的用途,是保证对执行环境有权访问的所有变量和函数的有序访问。

    为什么函数执行完成后打印函数对象只能看到global?为什么闭包会导致内存泄漏?这些都是作用域链底层导致

    1. var a = 1
    2. function fn () {
    3. var b = a + 1
    4. console.log(b)
    5. }
    6. // 查看创建时函数下的对象
    7. console.dir(fn);
    8. // fn()

    1.打印调用后的fn结果,发现只有一个Global对象。 

    2.在函数中打断点查看函数执行过程中创建的对象

    发现在函数创建到执行完成期间,会创建一个局部作用域即Local,执行完成后,这个Local会被销毁

    3.整个作用域链执行过程

    1. 首先在创建fn函数时,会创建一个预先包含全局变量对象的作用域链Global,这个作用域链被保存在内部的[[Scope]]属性中。
    2. 当调用fn函数时,会为函数创建一个执行环境Local(局部作用域)
    3. 然后通过复制函数的[[Scope]]属性中的对象构建起执行环境的作用域链
    4. 然后创建活动对象AO并推入执行环境的作用域链。(不懂?)
    5. 在fn执行完成后,作用域就会被销毁。只剩下预先创建的Global对象

     4.作用域链总结

    每个作用域链里面都有一个变量对象,其中函数所包含的称为活动对象AO(Active Object),每个函数包含着对上一个变量对象的引用,如果变量在当前作用域中找不到,就会通过作用域链找到他的上一级,上一级也找不到就会继续往上找,最终会找到window全局作用域,全局作用域也找不到就会打印not defined并报错。

    5.问题?内存泄漏在哪个环节出现问题?

    1. function books () {
    2. var book = '书包里面的书本'
    3. return function () {
    4. console.log(book)
    5. }
    6. }
    7. var bag = books()
    8. bag()

    整个执行过程:

    • 预先创建Global全局变量对象
    • books()创建时,先复制上级Global变量对象,然后创建Local局部作用域变量(注意这里books执行完成后并不会立即销毁)
    • bag()创建时,先复制Global变量对象和books的变量对象,然后创建自己的Local作用域对象,执行完成后销毁自己的Local作用域对象。

    整个过程中books()的Local作用域变量对象都不会被销毁。如果这种情况多了就会造成内存泄漏。

    books的Local作用域对象不是在books执行完立即销毁,这是由垃圾回收机制决定的,因为这里bag()函数还会读取Local变量对象中的数据,所以不会销毁。

    books的Local作用域为什么不会立即销毁?执行上下文中进行代码预编译时就会确认,global,books,bag这些函数的关系。这里发现bag()还会调用,所以就不会进行销毁

  • 相关阅读:
    git分支
    Java 包装类型 == 操作引发的 Bug
    IO多路复用实现TCP客户端与TCP并发服务器
    【Java牛客刷题】入门篇(01)
    PTA 7-170 公约数与公倍数
    【新知实验室-TRTC开发】实时音视频之欢度世界杯
    快速排序--简洁的JAVA/PHP实现
    大屏小程序探索实践 | Cube 技术解读
    IDEA Docker插件远程连接Docker,并打包部署启动SpringBoot项目
    极速Go语言入门(超全超详细)-进阶篇
  • 原文地址:https://blog.csdn.net/qq_34569497/article/details/133809473