【问题标题】:How do I subclass Raphael.st我如何继承 Raphael.st
【发布时间】:2014-05-12 16:16:59
【问题描述】:

我的图表应用程序中有许多逻辑对象,每个对象都包含许多 Raphael 对象。例如,一个数据点可能由一个圆圈和一个标题组成。

我希望能够将所有这些对象作为一个对象进行处理,并且还能够确定任何给定 Raphael 元素属于哪个逻辑对象(例如,处理鼠标点击该逻辑元素上下文中的元素它属于)。

我希望能够创建一个 Raphael.st 的子类(即 Raphael 集),并重写 push 方法将 element.data("object") 设置为包含的逻辑对象。

在代码的其他地方,我使用了以下子类方法(我在 Stack Overflow 上找到的):

/**
 * Utility function to help subclassing
 * @param base
 * @param sub
 */
function subclass(base, sub) {
    // Avoid instantiating the base class just to setup inheritance
    // See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create
    // for a polyfill
    sub.prototype = Object.create(base.prototype);
    // Remember the constructor property was set wrong, let's fix it
    sub.prototype.constructor = sub;
    // In ECMAScript5+ (all modern browsers), you can make the constructor property
    // non-enumerable if you define it like this instead
    Object.defineProperty(sub.prototype, 'constructor', {
        enumerable: false,
        value: sub
    });
}

但是,此方法会引发异常,因为当 base = Raphael.st 时 base.prototype 为 null。

对于我对子类化在 javascript 中的真正工作原理一无所知,我深表歉意 - 我意识到盲目地从其他地方复制代码并不理想,但我还没有找到我理解的解释!

谁能告诉我如何继承 Raphael.st,和/或指出一个解释的方向,让我自己弄清楚如何?

【问题讨论】:

    标签: javascript raphael subclassing


    【解决方案1】:

    继承 Raphael.set 不是一个好主意,因为 Raphael 并不期待它。例如,Raphael 中的很多代码需要知道它是否在处理一个集合,使用如下代码:

    if (element.constructor == R.st.constructor)
    

    这意味着适当的子类将无法通过测试。

    如果您仍想继续(并且没有任何冲突的属性或函数名称,就像我尝试它时所做的那样!),我确实找到了答案。

    子类函数需要修改,因为 Raphael 不遵循通常的约定——Raphael.st 不是类,它是类的原型。因此子类方法应该修改如下:

    function subclass(base, sub) {
    // Avoid instantiating the base class just to setup inheritance
    // See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create
    // for a polyfill
    sub.prototype = Object.create(base.prototype ? base.prototype : base);
    // Remember the constructor property was set wrong, let's fix it
    sub.prototype.constructor = sub;
    // In ECMAScript5+ (all modern browsers), you can make the constructor property
    // non-enumerable if you define it like this instead
    Object.defineProperty(sub.prototype, 'constructor', {
        enumerable: false,
        value: sub
    });
    }
    

    这是子类构造函数:

    /**
     * @param paper Raphael Paper
     */
    var MySet = function(paper) {
    Raphael.st.constructor.call(this);
    // Without this, Raphael does not recognise MySet objects as sets
    // because it tests constructor value using == instead of instanceof
    this.constructor = Raphael.st.constructor;
    // Cheat!! Copied this code from Raphael Paper.set()
    this.paper = paper;
    };
    
    subclass(Raphael.st, MySet);
    

    希望这对其他人有帮助!

    【讨论】:

      猜你喜欢
      • 2013-08-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-17
      • 1970-01-01
      • 2010-12-22
      • 2010-12-08
      • 1970-01-01
      相关资源
      最近更新 更多