preventing无限循环利用骨干风格的原型继承时 [英] Preventing infinite recursion when using Backbone-style prototypal inheritance
问题描述
我使用的是改编自一个骨干扩展功能(相同的除了一些改变以符合我的雇主的命名约定)来实现原型继承。建立结构如下(下大大简化)后,我得到一个无限循环。
I'm using an extend function adapted from Backbone (identical apart from a few changes to comply with my employer's naming conventions) to implement prototypal inheritance. After setting up the following structure (much simplified below) I get an infinite loop.
Graph = function () {};
Graph.extend = myExtendFunction;
Graph.prototype = {
generateScale: function () {
//do stuff
}
}
// base class defined elsewhere
UsageGraph = Graph.extend({
generateScale: function () {
this.constructor._super.generateScale.call(this); // run the parent's method
//do additional stuff
}
})
ExcessiveUsageGraph = Graph.extend({
// some methods, not including generateScale, which is inherited directly from Usage Graph
})
var EUG = new ExcessiveUsageGraph();
EUG.generateScale(); // infinite loop
循环正在发生的事情,因为 ExcessiveUsageGraph
上升原型链 UsageGraph
来运行的方法,但这个
仍设置为 ExcessiveUsageGraph
所以,当我使用 this.constructor._super
来运行它也更进了一步链条 UsageGraph
,并再次调用同样的方法父类的方法。
The loop is happening because ExcessiveUsageGraph
goes up the prototype chain to UsageGraph
to run the method, but this
is still set to an instance of ExcessiveUsageGraph
so when I use this.constructor._super
to run the parent method it also goes one step up the chain to UsageGraph
and calls the same method again.
我怎么能引用父方法从骨干风格的原型内避免这种循环。我也想尽量避免通过名称引用父类。
How can I reference parent methods from within a Backbone-style prototype and avoid this kind of loop. I also want to avoid referring to parent classes by name if possible.
推荐答案
你到JavaScript的这个
和原型继承的限制之一运行,正视因为你'重新尝试创建一种语言的一类,如继承方案,它不直接支持它。
You're running in to one of the limitations of JavaScript's this
and prototypal inheritance, squarely because you're attempting to create a class-like inheritance scheme in a language that doesn't directly support it.
即使骨干,您通常使用的超级望而却步直接,因为你已经列出,并限制了。
Even with Backbone, you are generally discouraged from using "super" directly because of the limitations that you've outlined, and more.
常见的解决方法是直接调用您的原型对象,而不是试图通过使用一个超级参考掩盖它。
The common solution is to call your prototype object directly, instead of trying to mask it through the use of a "super" reference.
UsageGraph = Graph.extend({
generateScale: function () {
Graph.prototype.generateScale.call(this); // run the parent's method
//do additional stuff
}
})
在工作的jsfiddle: http://jsfiddle.net/derickbailey/vjvHP/4/
In a working JSFiddle: http://jsfiddle.net/derickbailey/vjvHP/4/
这部作品的原因是在JavaScript中本的事情。当你调用一个函数时,this关键字是基于你如何调用该函数,而不是在这里被定义的函数集。
The reason this works has to do with "this" in JavaScript. When you call a function, the "this" keyword is set based on how you call the function, not where the function is defined.
在调用generateScale的方法在此code的情况下,它调用generateScale功能,设置的上下文的点表示法。换句话说,因为code读 prototype.generateScale
,函数调用(以下简称本关键字)的情况下被设置为原型
对象,这恰好是图
构造函数的原型。
In the case of calling the "generateScale" method in this code, it's the dot-notation of invoking the generateScale function that sets the context. In other words, because the code reads prototype.generateScale
, the context of the function call (the "this" keyword) is set to the prototype
object, which happens to be the prototype of the Graph
constructor function.
由于 Graph.prototype
现在呼叫到 generateScale
的背景下,该功能将与运行背景和行为,你期待。
Since the Graph.prototype
is now the context of the call to generateScale
, that function will run with the context and behavior that you are expecting.
相反,如果你的呼吁, this.constructor._super.generateScale
,允许你的JavaScript歪斜的背景下,你没有因为期望的方式在在启动这个
关键字。
Conversely, when you made the call to this.constructor._super.generateScale
, you allowed JavaScript to skew the context in a manner that you didn't expect because of the this
keyword at the start.
这是你的层次结构的第三层是造成这一问题与本。你打电话 EUG.generateScale
,其中明确制定这个
到 EUG
实例。为 generateScale
方法的原型查找到达回图
原型来调用该方法,因为该方法未找到在 EUG
实例直接。
It's the 3rd level of your hierarchy that's causing the problem with "this". You're calling EUG.generateScale
, which is explicitly setting this
to the EUG
instance. The prototypal lookup for the generateScale
method reaches back to the Graph
prototype to call the method, because the method is not found on the EUG
instance directly.
但这个
已设置为 EUG
实例和JavaScript的原型查找方面这个
。所以,当UsageGraph原型 generateScale
被称为这个
设置为 EUG
实例。因此,调用 this.constructor .__超级__
将被从 EUG
实例评估,是要找到UsageGraph作为原型的__ __超级
的值,这意味着你要再次调用同一个对象的同一个方法,用同样的背景。因此,一个无限循环。
But this
has already been set to the EUG
instance, and JavaScript's prototypal lookup respects this
. So, when the UsageGraph prototype generateScale
is called, this
is set to the EUG
instance. Therefore, calling this.constructor.__super__
is going to be evaluated from the EUG
instance and is going to find the UsageGraph prototype as the value of __super__
, which means you're going to call the same method on the same object, with the same context again. Thus, an infinite loop.
该解决方案不使用这个
原型中查找。直接使用命名函数和原型,我在解决方案,并表现出的jsfiddle
The solution is not to use this
in prototypal lookups. Use the named function and prototype directly, as I showed in the solution and JSFiddle.
这篇关于preventing无限循环利用骨干风格的原型继承时的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!