内存泄露问题

内存泄露问题

这是我在其他地方看到的一道题:

var theThing = null;

var replaceThing = function () {

  var originalThing = theThing;

  var unused = function () {

    if (originalThing) // 'originalThing'的引用

      console.log("嘿嘿嘿");

  };

  theThing = {

    longStr: new Array(1000000).join('*'),

    someMethod: function () {

      console.log("哈哈哈");

    }

  };

};

setInterval(replaceThing, 1000);

对于这段代码,老师的解释是:

要想揪出其中的问题,大家需要对 V8 引擎有所了解,尤其是这一点:在 V8 中,一旦不同的作用域位于同一个父级作用域下,那么它们会共享这个父级作用域。

在这段代码里, unused 是一个不会被使用的闭包,但和它共享同一个父级作用域的 someMethod,则是一个 “可抵达”(也就意味着可以被使用)的闭包。unused 引用了 originalThing,这导致和它共享作用域的 someMethod 也间接地引用了 originalThing。结果就是 someMethod “被迫” 产生了对 originalThing 的持续引用,originalThing 虽然没有任何意义和作用,却永远不会被回收。不仅如此,originalThing 每次 setInterval 都会改变一次指向(指向最近一次的 theThing 赋值结果),这导致无法被回收的无用 originalThing 越堆积越多,最终导致严重的内存泄漏。

我在控制台运行了一下这段代码,结果是 输出了 179921,不理解啊。

我有以下几点疑问:

1、为什么这段代码执行完,会输出一个数呢?这个数怎么得到的呢?

2、unused为什么和someMethod是共享同一个父级作用域的?someMethod不是theThing 的值的一部分吗?

3、为什么,unused 引用了originalThing,和它共享作用域的someMethod也间接地引用了originalThing?

4、这段代码里的函数都没有被执行呀,那里面的函数不就都是不会被使用的吗?

5、每次 setInterval之后,originalThing 都会指向最近一次的 theThing 赋值结果,originalThing

不是只是改变了指向吗,它还是只有一个啊,怎么会导致无用的originalThing 越堆积越多呢?

正在回答

登陆购买课程后可参与讨论,去登陆

2回答

同学你好,对于你的问题解答如下:

  1. 老师测试同学粘贴的代码,控制台没有打印任何内容,同学再测试下

  2. 因为ES5中只有全局作用域和函数作用域,对象的{}不是一个作用域。unused和someMethod都处于replaceThing函数作用域下,所以说unused和someMethod是共享一个父级作用域

  3. 因为闭包unused中引用了originalThing,导致originalThing变量一直保存在内存中,是共享的,那么在replaceThing函数中定义的闭包方法,都可以使用originalThing这个变量,所以说someMethod也间接的引用了originalThing

  4. 这段代码中的,只有replaceThing函数每隔一秒调用一次,在执行replaceThing方法时,内部定义的theThing对象下的longStr属性对应的new Array(1000000).join('*')会被执行。

    但是unused和someMethod方法没有被执行。

  5. 定时器每隔一秒钟,就会调用一次replaceThing方法,theThing都会被重新赋值,产生一个someMethod闭包, originalThing指向最近一次的theThing,确实只改变了指向,但是由第三条分析可知,someMethod中间接引用了originalThing,所以就算theThing重新赋值了,它的上一次值并不会被回收,导致越堆积越多。

本站的教学服务只包含站内视频内容问题解答、站内习题问题解答、站内作业问题解答、站内测试题问题解答以及站内产品使用问题解答。同学的问题是在其他地方看到的题,与本站视频、习题以及作业等内容无关联,故不包含在本站的教学服务内。但是看同学比较爱学习,所以老师这次破例为你讲解。

老师这里给同学一个小小的建议,在其他地方看到代码存在疑问,推荐同学跟发帖的人直接交流沟通,这样获取的信息更加直观准确。

祝学习愉快~

  • Aurora_Meteor 提问者 #1
    我是在浏览器的控制台运行的代码,每次运行它都会出现一个不同的数字的。 这个题是在慕课网的一个专栏里看到的...但是那个作者不回复,只好在这里问老师了....
    2020-07-13 12:02:32
好帮手慕慕子 2020-07-13 15:36:22

同学你好,对于你的问题解答如下:

  1. 直接在控制台运行代码,返回的数字是指,在执行setInterval方法时,默认返回一个对应的ID。

  2. 由于老师不了解专栏讲解的完整内容,只能针对同学粘贴的部分代码进行解答,可能会不够全面,所以更推荐同学在专栏下提问,得到的解答会更加全面,而且其他正在学习专栏的同学可能也会帮助同学解答,同学也可以和其他一起学习的小伙伴们多交流交流。

祝学习愉快~

问题已解决,确定采纳
还有疑问,暂不采纳

恭喜解决一个难题,获得1积分~

来为老师/同学的回答评分吧

0 星
2.组件化网页开发
  • 参与学习           人
  • 提交作业       1121    份
  • 解答问题       14456    个

本阶段在运用JS实现动态网页开发的基础上,带你深入理解企业开发核心思想,完成一个企业级网页的开发,体验前端工程师的成就感。

了解课程
请稍等 ...
意见反馈 帮助中心 APP下载
官方微信

在线咨询

领取优惠

免费试听

领取大纲

扫描二维码,添加
你的专属老师