最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • [JS红宝书笔记]变量、作用域与内存

    正文概述 掘金(JayeZhu)   2020-12-09   706

    序言

    首先回顾一下上一章节:介绍了 JavaScript 的语法、变量声明、数据类型、操作符、语句还有函数。今天第四更底层的知识,做好笔记,开始。

    MIND

    [JS红宝书笔记]变量、作用域与内存

    原始值和引用值

    ECMAScript 变量包括原始值引用值两种,有以下区别:

    • 构成:原始值就是最简单的数据,而引用值是多个值构成的对象
    • 访问:保存原始值的变量是按值访问,操作存储在变量中的实际值;保存引用值的变量是按引用访问,实际操作的是对该对象的引用
    • 动态属性:原始值不能有属性,而引用值有,而且可以动态添加、修改和删除属性(和方法)
    • 复制值:变量赋给另一个变量时,两者都是将变量中的值复制到新变量所在的位置,但原始值复制的值是值的副本,而引用值是指向存储在堆内存中的对象的指针

    传递参数

    无论原始值还是引用值,向函数传递参数时,都是按值传递,也就是说跟原始值和引用值的复制一样地传递方式-——将函数外的值复制到函数内部的参数。在 ECMAScript 中,函数的参数就是局部变量,因此,按值传递的值会被复制到一个局部变量。

    确认类型

    上一章节数据类型检测的操作符 typeof 用来检测原始值还行,可是遇到引用值就只会 "object" 这一套,连 null 都算进去。instanceof 就可以解决问题。

    const colorList = ['green', 'yellow', 'cyan'];
    console.log(colorList instanceof Array); // true
    

    注意,用 instanceof 检测原始值返回 false

    执行上下文

    这是该章节最为重要的知识点,可能需要后面知识量贯通更好理解,这里仅仅讲述一些概念。

    执行上下文(Execution Context),简称 EC

    • 来源:JS 引擎执行可执行代码前,进行代码解析,创建执行上下文
    • 含义:决定变量或函数可以访问哪些数据,还有决定它们的行为,是 JS 的执行环境
    • 分类:全局执行上下文、函数执行上下文、eval 执行上下文(很少使用)
    • 组成元素:变量对象(Variable object,VO)、作用域链(Scope chain)、this(后面章节介绍)
    • 管理:执行上下文栈(Execution context stack,ECS)

    执行上下文栈

    • 全局执行上下文:最外层的上下文,同时也是执行上下文栈中最下层。任何不在函数内部的代码都会在全局上下文中
    • 每当函数被调用,都会为该函数创建一个新的上下文

    用来管理执行上下文,当 JS 开始解释执行代码时,首先遇到全局执行代码,初始化时将对应的全局执行上下文押人员栈底,等待程序执行完毕后才会清空。程序执行中遇到函数执行代码,创建函数执行上下文,压入执行上下文栈,等待函数执行完毕,遵从栈的后进先出规则,函数执行上下文会从栈中弹出

    变量对象

    变量对象存放上下文中所定义的所有变量和函数,无法通过代码访问,用于后台处理数据。

    全局对象

    全局上下文中的变量对象就是全局对象,根据不同的宿主环境而产生差异,在浏览器中,全局对象是 window 对象。全局对象是预定义的对象,作为 JS 的全局函数和全局属性的占位符,通过使用全局对象可以访问所有其他预定义的对象、函数和属性。

    活动对象

    函数执行上下文中,将活动对象(activation object,AO)作为变量对象。活动对象是进入函数执行上下文时被创建的,通过函数的 arguments 属性初始化。本身与边来那个对象是一个东西,但不同的是,活动对象是激活的变量对象,该对象上的各种属性可以访问。

    作用域链

    作用域链决定了各级上下文中的代码在访问变量和函数的顺序,其本质是一个变量对象的指针列表,其中全局变量始终位于作用域链的最前端。当查找变量时,会从当前执行上下文的变量对象中查找,如果没有找到,就会从父上下文的变量对象中查找,直到找到全局变量。

    作用域链增强

    除了三种执行上下文外,可通过在作用域链前端临时添加上下文来增强作用域链,通常有两种方式:

    • try/catch 语句的 catch 语句
    • with 语句

    推荐

    这部分需要好好理解,推荐以下文章细细咀嚼:

    • 冴羽
      • 上下文栈
      • 变量对象
      • 作用域链
      • 执行上下文
    • cavszhouyou
      • 执行上下文
      • 变量对象
      • 作用域链
      • 执行上下文示例分析

    作用域

    变量提升

    var 声明变量时,变量会自动添加到最接近的上下文,即全局上下文或函数上下文中,被拿到全局作用域或函数作用域的顶部,位于作用域中所有代码之前,形成变量提升

    暂时性死区

    let 声明变量其实也存在变量提升,但它形成的块级作用域有暂时性死区,不能在声明前使用 let 声明的变量,因此看起来变量没有提升。

    垃圾回收

    JS 通过自动内存管理实现内存分配和闲置资源回收。

    • 思路:确定不再使用的变量,然后释放该变量所占内存。
    • 缺陷:难以判定变量是否不再使用
    • 解决:采用标记策略跟踪变量是否还会使用,主要有:标记清理和引用计数

    标记清理

    垃圾回收时,首先标记内存中存储的所有变量,然后将所有在上下文中的变量,以及这些变量引用的变量的标记去除。最后垃圾回收程序进行内存清理,销毁带标记的所有值并收回它们的内存。

    引用计数

    不常用的策略。思路是对每个值都记录它被引用的次数,初始声明时次数为 1,该值随保存该值的变量而变动,当变量被引用赋值加 1,被其他值覆盖时减 1。如果引用值为 0,则在垃圾回收时释放该值内存

    性能

    垃圾回收程序的周期性运行会影响到程序的运行,造成性能损失。各个浏览器引擎会基于 JS 运行时环境的探测来决定何时运行,各有差异。其中 Chrome 的 V8 是根据活跃对象的数量增加一些余量,而 IE 是分配固定的数目,性能不堪。

    内存管理

    为了避免运行大量 JS 导致网页耗尽内存,浏览器所分配到的内存是限制住的。需要优化内存占用:

    • 解除引用:不需要的数据,设置为 null,等待释放
    • 声明优化:不使用 var,优先使用 const,然后是 let,后两者能更快进入到垃圾回收
    • 隐藏类:避免通过隐藏类动态的添加属性赋值,在构造函数中提前一次性声明
    • 避免内存泄漏:避免意外声明全局变量、定时器设有关闭语句、谨慎使用闭包
    • 静态分配和对象池:静态分配是极端形式,不考虑。对象池策略是创建对象池来管理可回收对象,不需要初始化对象,避开垃圾回收检测,因此不会频繁触发垃圾回收程序

    总结

    这一章笔记很空洞,emmmm,但都是很重要的内容,需要多看看其他文章,或者说红宝书其他章节都知晓的情况下更容易总结。所以,下一章:基本引用类型。


    起源地下载网 » [JS红宝书笔记]变量、作用域与内存

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元