我一直在探索各种MV*框架中的模式,今天我注意到一个奇怪的模式,这似乎会导致一些问题
模型原型。具有属性collections: []
集合原型。具有属性models: []
当一个集合获得一个新的模型时,它会被推入collection.models,但模型本身也会被修饰为知道它是哪个集合的成员--即集合实例被推入model.collections。
因此,model.collections[0]是一个包含.models[0]的集合,它是具有集合属性的模型...诸若此类。
最基本的情况是:
var A = function() {
this.collections = [];
},
B = function() {
this.models = [];
this.add = function(what) {
what.collections.push(this);
this.models.push(what)
};
};
var model = new A();
var collection = new B();
collection.add(model);这是有罪的一方在行动:https://github.com/lyonbros/composer.js/blob/master/composer.js#L310-313,然后再往下推模型:https://github.com/lyonbros/composer.js/blob/master/composer.js#L781-784
我认为将会有一定程度的懒惰评估--只有在需要的时候才会使用这些东西。这段代码--就是它自己--是有效的。
但我也在通过buster.js编写测试,我注意到所有依赖于sinon.spy()的测试都产生了InternalError: too much recursion (FF)或RangeError: Maximum call stack size exceeded(Chrome)。捕获的FF甚至毫无反应地崩溃了,这是我以前在buster测试驱动程序中从未遇到过的-它甚至在我的午休时间使用了3.5 my的内存。
经过大量的调试,我撤销了引用存储,突然,一切都恢复正常了。诚然,删除spy()断言也是有效的,但这不是重点。
因此,问题是-拥有这样的代码,它是可接受的吗,浏览器将如何解释它,瓶颈是什么,以及如何使用指向模型所属集合的指针(可能是集合控制器和集合uids或其他东西)来装饰模型。
失败的buster.js测试的全部要点:https://gist.github.com/2960549
发布于 2012-06-21 03:26:24
浏览器并不关心。问题是您使用的工具无法通过对象图检查循环引用链。这些是完全合法的,至少如果你想要并期待它们的话是这样的。
如果您想到一个对象及其属性,以及通过这些属性直接或间接引用的对象,那么该程序集就构成了一个图。如果可以跟踪引用并返回到开始的位置,那么这意味着图有一个循环。这绝对是一件好事,该语言允许循环。它是否适用于给定的系统取决于相关的代码。
因此,例如,如果一个递归函数遍历一个对象图,而没有检查它是否已经访问了一个对象,那么如果这个图是循环的,那么它肯定会触发“太多的递归”错误。
发布于 2012-06-21 03:29:42
将只有两个对象相互引用(称为“循环引用”)。
var a, b = {a: a={b: b}};
// a.b: pointer to b
// b.a: pointer to a根本没有递归。如果您收到too much recursion或Maximum call stack size exceeded错误,则需要有一个被调用太频繁的函数。例如,当你试图克隆对象并在属性上递归而不关心循环引用时,可能会发生这种情况。您需要进一步查看您的代码,错误消息还应该包括一个(非常长的)调用堆栈。
https://stackoverflow.com/questions/11126643
复制相似问题