jQuery'原型部分继承失败

Inheritance of jQuery's prototype partially fails

本文关键字:继承 失败 原型部 jQuery      更新时间:2023-09-26

我想用Coffeescript创建一个UIObject类。这个类应该继承自jQuery,这样UIObject的实例就可以被使用,就好像它们是用jQuery创建的。

class UIObject
  isObject: (val) -> typeof val is "object"
  constructor: (tag, attributes) ->
    @merge jQuery(tag, attributes), this
    @UIObjectProperties = {}
  merge: (source, destination) ->
    for key of source
      if destination[key] is undefined
        destination[key] = source[key]
      else if @isObject(source[key])
        @merge(source[key], destination[key])
    return

部分有效。考虑下面的Foobar类:

class Foobar extends UIObject
  constructor: -> super("<h1/>", html: "Foobar")

$("body").append(new Foobar)工作良好。BUT: (new Foobar). appendto ("body")放置标签,但也引发RangeError: Maximum call stack size exceeded

继承jQuery是一个坏主意吗?或者有解决方案吗?

对于那些不知道CoffeeScript的人,JavaScript源代码是:

    var Foobar, UIObject;
    var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) {
        for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; }
        function ctor() { this.constructor = child; }
        ctor.prototype = parent.prototype;
        child.prototype = new ctor;
        child.__super__ = parent.prototype;
        return child;
    };
UIObject = (function () {
    UIObject.prototype.isObject = function (val) {
        return typeof val === "object";
    };
    function UIObject(tag, attributes) {
        this.merge(jQuery(tag, attributes), this);
        this.UIObjectProperties = {};
    }
    UIObject.prototype.merge = function (source, destination) {
        var key;
        for (key in source) {
            if (destination[key] === void 0) {
                destination[key] = source[key];
            } else if (this.isObject(source[key])) {
                this.merge(source[key], destination[key]);
            }
        }
    };
    return UIObject;
})();
Foobar = (function () {
    __extends(Foobar, UIObject);
    function Foobar() {
        Foobar.__super__.constructor.call(this, "<h1/>", {
            html: "Foobar"
        });
    }
  return Foobar;
})();

这确实有点难以实现(但很有创意!),因为jQuery和CoffeeScript类都有关于.constructor()方法的想法。

在jQuery 1.6.4(今天CoffeeScript主页上使用的)中,在jQuery本身的第246行创建了一个无限递归,在这行代码中:

var ret = this.constructor();
这里的

this指向您的构造函数,但jQuery希望它指向自己。你的@merge()方法没有正确地替换构造函数。还有一种更黑客的方法,将@merge()方法更改为:

merge: (source, destination) ->
  for key of source
    if destination[key] is undefined
      destination[key] = source[key]
    else if @isObject(source[key])
      @merge(source[key], destination[key])
  @constructor = jQuery

在"Try coffeescript"下的随机测试表明它可以工作,但我要小心以后可能会出现奇怪的效果,所以如果您继续使用这种方法,请彻底测试。