美文网首页
How JavaScript Work 学习笔记(二)

How JavaScript Work 学习笔记(二)

作者: VioletJack | 来源:发表于2019-03-19 20:42 被阅读0次

    本文是我看 How JavaScript Work 系列文章的学习笔记。
    英文原文地址:https://blog.sessionstack.com/tagged/tutorial
    中文翻译版地址:https://github.com/Troland/how-javascript-works

    必须理解 JavaScript 的内存管理

    虽然 JavaScript 看似是做到了自动释放内存,但其实这种自动的能力只是一种内存管理策略,代码编写不当必然会引起内存泄漏。所以想写好 JavaScript 必须理解内存管理。

    内存的生命周期

    内存生命周期一共分为3步,分别是:

    • 分配内存
    • 使用内存
    • 释放内存

    JavaScript 中的内存

    分配内存

    在 JavaScript 中分配内存的方式就是定义变量、对象或方法:

    var n = 374; // 为数字分配内存
    var s = 'sessionstack'; // 为字符串分配内存
    
    var o = {
      a: 1,
      b: null
    }; // 为对象及其值分配内存
    
    var a = [1, null, 'str']; // (类似对象)为数组及其数组元素值分配内存
    
    function f(a) {
      return a + 3;
    } // 分配一个函数(一个可调用对象)
    
    // 函数表达式也分配一个对象
    someElement.addEventListener('click', function() {
      someElement.style.backgroundColor = 'blue';
    }, false);
    

    使用内存

    使用内存就是对所定义的变量、对象或函数进行读写操作。读就是获取变量、写则是赋值变量、修改对象、函数传参等行为。

    释放内存

    释放内存有两种算法方案:引用计数和标记清除。

    引用计数就是指记录内存被引用的次数,如果次数变为 0 则可以释放。
    标记清除则复杂一些,下面是标记清除的逻辑:

    • 根:一般来说,根指的是代码中引用的全局变量。就拿 JavaScript 来说,window 对象即是根的全局变量。Node.js 中相对应的变量为 "global"。垃圾回收器会构建出一份所有根变量的完整列表。
    • 随后,算法会检测所有的根变量及他们的后代变量并标记它们为激活状态(表示它们不可回收)。任何根变量所到达不了的变量(或者对象等等)都会被标记为内存垃圾。
    • 最后,垃圾回收器会释放所有非激活状态的内存片段然后返还给操作系统。

    我理解就是通过遍历变量标记激活的变量,并且将失效的变量进行内存释放。

    这两种方案中标记清除是 JavaScript 最常用的释放内存方案。

    四种常见的 JavaScript 内存泄漏

    • 全局变量 —— 由于 JavaScript 在非严格模式下会为未定义的变量定义一个全局变量,就会造成一些变量的内存泄漏。
    • 定时器和被遗忘的回调函数 —— 回调函数作为函数必然是占用内存的,如果回调函数被定时器、事件监听器使用,函数所在内存就不会被释放。
    • 闭包 —— 闭包能够长期持有函数内变量数据想必大家都知道,所以也要注意在不用闭包的时候释放内存。
    • 源自 DOM 的引用

    内存优化方案总结

    1. 使用 CSS3、SVG、IconFont、Canvas 替代图片。展示大量图片的页面,建议使用 Canvas 渲染而非直接使用img标签。具体详见 Javascript的Image对象、图像渲染与浏览器内存两三事
    2. 适当压缩图片,可减小带宽消耗及图片内存占用。
    3. 使用恰当的图片尺寸,即响应式图片,为不同终端输出不同尺寸图片,勿使用原图缩小代替 ICON 等,比如一些图片服务如 OSS。
    4. 使用恰当的图片格式,如使用WebP格式等。详细图片格式对比,使用场景等建议查看web前端图片极限优化策略
    5. 按需加载及按需渲染图片。
    6. 预加载图片时,切记要将 img 对象赋为 null,否则会导致图片内存无法释放。当实际渲染图片时,浏览器会从缓存中再次读取。
    7. 将离屏 img 对象赋为 null,src 赋为 null,督促浏览器及时回收内存及像素格式内存。
    8. 将非可视区域图片移除,需要时再次渲染。和按需渲染结合时实现很简单,切换 src 与 v-src 即可。

    我只是个搬运工

    声明下,本文是我的学习笔记,原汁原味还请查看原文

    相关文章

      网友评论

          本文标题:How JavaScript Work 学习笔记(二)

          本文链接:https://www.haomeiwen.com/subject/piaimqtx.html