javascript – 在使用Backbone样式的原型继承时防止无限递归

我正在使用一个改编自Backbone的扩展功能(除了一些改变,以符合我雇主的命名惯例),以实现原型继承.在设置了以下结构(下面简化得很简单)之后,我得到了一个无限循环.
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并再次调用相同的方法.

如何从Backbone样式的原型中引用父方法并避免这种循环.如果可能的话,我还想避免按名称引用父类.

编辑Here’s a fiddle demonstrating that this happens in Backbone

解决方法

您正在尝试使用JavaScript和原型继承的其中一个限制,因为您试图使用不直接支持它的语言创建类类继承方案.

即使使用Backbone,由于您已经概述的限制等等,您通常不会直接使用“超级”.

解决问题

常见的解决方案是直接调用原型对象,而不是试图通过使用“超级”引用来掩盖它.

UsageGraph = Graph.extend({
   generateScale: function () {
       Graph.prototype.generateScale.call(this); // run the parent's method
       //do additional stuff
   }
})

一个有效的JSfiddlehttp://jsfiddle.net/derickbailey/vjvHP/4/

这个工作的原因与JavaScript中的“this”有关.调用函数时,“this”关键字是根据调用函数的方式设置的,而不是函数定义的位置.

在此代码调用“generateScale”方法的情况下,它是调用设置上下文的generateScale函数的点符号.换句话说,因为代码读取prototype.generateScale,函数调用的上下文(“this”关键字)被设置为原型对象,它恰好是Graph构造函数的原型.

由于Graph.prototype现在是对generateScale的调用的上下文,因此该函数将运行您期望的上下文和行为.

为什么this.constructor.super失败了

相反,当您调用this.constructor._super.generateScale时,您允许JavaScript以您不期望的方式扭曲上下文,因为在开始时使用this关键字.

这是您的层次结构的第3级导致“this”的问题.您正在调用EUG.generateScale,它明确将此设置为EUG实例. generateScale方法的原型查找返回到Graph原型以调用方法,因为该方法不能直接在EUG实例上找到.

但是这已经被设置为EUG实例,并且JavaScript的原型查找尊重这一点.因此,当调用UsageGraph原型generateScale时,将其设置为EUG实例.因此,调用this.constructor .__ super__将从EUG实例进行评估,并将找到UsageGraph原型作为__super__的值,这意味着您将在同一个对象上调用相同的方法,并使用相同的方法上下文.因此,一个无限循环.

解决方案不是在原型查找中使用它.正如我在解决方案和JSfiddle中所展示的那样,直接使用命名函数和原型.

相关文章

前言 做过web项目开发的人对layer弹层组件肯定不陌生,作为l...
前言 前端表单校验是过滤无效数据、假数据、有毒数据的第一步...
前言 图片上传是web项目常见的需求,我基于之前的博客的代码...
前言 导出Excel文件这个功能,通常都是在后端实现返回前端一...
前言 众所周知,js是单线程的,从上往下,从左往右依次执行,...
前言 项目开发中,我们可能会碰到这样的需求:select标签,禁...