它们只是来自node.js官方文档的几行内容。这个nodejs代码是循环引用吗?
client.on('data', function(data) {
console.log(data.toString());
client.end();
});
我觉得客户端对象引用了回调,回调函数对客户端对象有一个闭包引用。那是对的吗?如果是的话,为什么这是鼓励?
它们只是来自node.js官方文档的几行内容。这个nodejs代码是循环引用吗?
client.on('data', function(data) {
console.log(data.toString());
client.end();
});
我觉得客户端对象引用了回调,回调函数对客户端对象有一个闭包引用。那是对的吗?如果是的话,为什么这是鼓励?
是的,这是一个循环引用,但它不是内存泄漏。仅仅给出这个代码片段,你只有一小部分对象的小图,但是,只要client
可以从主程序到达,所有这些对象将永远不会有资格进行垃圾回收。但是,如果您要设置client = null;
,则包含client
对象和匿名事件处理程序函数的对象图将无法从主程序访问,因此符合垃圾回收的条件,因此适用于A-OK。
这种模式本身并不是内存泄漏。如果你要在一个循环中创建客户端,并在一个数组或对象中保留一个对所有这些客户端的引用,并且没有代码来处理陈旧的客户端,那么是的,那就是内存泄漏。
谢谢。可能会有更复杂的循环引用。我可以说两个互相引用的对象,无论是直接的还是间接的,它们都会被V8垃圾回收?只有当其中一个被第三个对象引用时,才会有内存泄漏? – 2013-03-02 08:31:29
这是正确的。如果从代码的可运行部分中无法访问整个大对象图,那么整个图就有资格进行垃圾回收。大多数典型的代码模式(如上述)不会导致泄漏。在使用对象或数组作为缓存,地图,集合等时应保持警惕,因为这些可能是添加但从不删除错误泄漏的候选对象。 – 2013-03-02 15:09:45
这是正确的。 node.js中的事件发射器将其监听器存储在私有_listeners属性中。 您的处理程序函数使用client
作为封闭变量,这并非严格必要,因为所有处理程序都使用事件发件人作为this
引用进行调用。
然而,使用this
代替client
不会改变的事实,client
是在封闭的,因为它不使用它只是暗示V8取消对它的引用从封闭。
即使从闭包中使用它,V8也有足够的逻辑来处理这种循环引用并将它们从内存中正确释放。
谢谢。所以我们不应该担心这种模式中的循环引用? – 2013-03-02 08:18:45
回调函数中的'client'由于范围而引用原始客户端,所以除非您重新定义它,否则它不能引用任何其他'客户端'。这不会导致任何范围问题,因此可以安全使用。唯一的另一种方式是将客户端作为参数传递(您无法控制框架所传递的内容),或者将客户端定义在另一个作用域中,如'window',这可能会引入更多问题并且没有任何改进。 – 2013-03-01 14:29:08