我怀疑以下设计模式是否会导致内存泄漏
我已经成功地使用它已经有一段时间了,但是我还没有看到其他人使用过这种模式,所以如果你看到它出了问题,我想要一些确认。
从下个月开始,我必须开始研究一个大型项目,我想知道我可以毫无问题地使用它,或者我应该使用其他策略。
controller.js:
var Controller = function(options){
};
Controller.prototype.makeView = function(options){
options.controller = this;
options.otheroption = options.otheroption;
var view = new View(options);
};
Controller.prototype.getModel = function(options){
//--- Get model ---
var model = new Model();
var promise = model.fetch();
return promise;
});
view.js:
var View = Backbone.View.extend({
initialize: function(options){
this.controller = options.controller;
this.otheroption = options.otheroption;
},
getModel: function(){
var promise = this.controller.getModel();
promise.done(_.bind(function(model){
//Do something with the returned model instance
}, this));
};
});
实例化控制器,例如。来自路由器或其他控制器:
//--- Instantiate the controller and build the view ---//
var controller = new Controller();
controller.makeView(options)
对我来说,这看起来不像循环引用,因为控制器和视图都被声明为局部变量。 然而,实例化的视图可以访问控制器功能,这允许我通过视图使用的模型/集合来隔离RESTful服务器交互。
对我来说,似乎剩下的唯一引用就是保持对控制器对象的引用的视图。 之后我做的是清理视图(当我不再需要它时,我会销毁实例及其引用。
您对此模式的看法表示高度赞赏 我的目的是在单独的控制器文件中隔离视图/服务器交互的创建:如果您在我的方法中看到漏洞并有更好的方法,请分享。
感谢。
答案 0 :(得分:3)
在这里做什么控制器看起来像是一个实用工具。可以由全球级单身人士轻松管理。我第一眼就看到了一些问题。
我宁愿编写一个可以为我创建和部署视图的实用程序函数。
var deployView = function(view, config){
//do the view rendering
view.render();
view.$el.appendTo(config.el);
}
var createView = function(config) {
var view;
var viewType = 'model';
if (config.collection || config.Collection) {
viewType = 'collection';
}
if (viewType === 'model') {
if (config.Model) {
config.model = new config.Model(config.modelAttributes);
//fetch if needed
}
} else {
if (config.Collection) {
config.collection = new config.Collection(config.items);
//fetch if needed
}
}
var filteredConfig = _.omit(config, 'Collection', 'Model', 'View');
view = new config.View(filteredConfig);
deployView(view, filteredConfig)
}
答案 1 :(得分:3)
简短回答:您发布的代码中没有内存泄漏问题。视图包含对控制器的引用,但反之亦然。因此,只要控制器的寿命比视图长,该引用就不会使您的对象不被垃圾收集。我在代码中的任何地方都没有看到循环引用。
更长的答案:陷阱将出现在未发布的代码中。特别是,您的视图中的任何事件处理程序都必须正确清理,否则您的视图never fade into oblivion。但是你已经在你的问题中说你清理了你的观点,所以我猜你知道那种问题。
答案 2 :(得分:1)
JavaScript实现很长一段时间没有圆形引用的问题。 (如果我没记错的话,IE6确实有来自循环引用的内存泄漏,这段时间内任何其他主要浏览器都没有共享。)
现代JavaScript实现通过“标记和扫描”算法执行垃圾收集。首先,他们从全局对象开始扫描您的Web应用程序的整个内存结构,并标记他们找到的所有内容。然后他们扫描存储在内存中的每个对象,垃圾收集任何未标记的内容。只要没有从全局对象或任何存储函数引用您的对象,就可以对其进行垃圾回收。
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Memory_Management#Mark-and-sweep_algorithm
您可能正在考虑基于引用计数的实现,它确实存在循环引用中的内存泄漏问题。在该实现中,只要一个对象包含对另一个对象的引用,该第二个对象就不能被垃圾回收。该方法曾经在Web浏览器中使用过,但现在已经不再使用了。
如今,大多数内存泄漏来自全局可访问的对象,您忘记清理并意外地将数据保留在函数闭包中(一个创建另一个函数并将其传递/保存到某处的函数)。由于闭包的局部变量可以由它们内部创建的函数访问,所以只要该函数存在就必须保留它们。
所以继续添加你想要的所有循环引用。除非您需要以IE6为目标,否则您的代码就可以了。