2011-11-25 49 views
4

我想使用Coffeescript來創建一個UIObject類。這個類應該從jQuery繼承,這樣UIObject的實例可以像使用jQuery創建的那樣使用。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)工作正常。但:(新的Foobar).appendTo(「body」)放置標籤,但也提高RangeError: Maximum call stack size exceeded

從jQuery繼承是不是一個好主意?還是有solurion?

對於那些誰也不知道的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; 
})(); 
+0

也許jQuery實例有自己的內部引用。 – Pointy

+1

......我的意思是你的「合併」函數會遇到無限遞歸問題。在這樣的深層複製操作中防止這種情況相當複雜。 – Pointy

回答

0

這確實有點難以實現的,因爲這兩個jQuery和CoffeeScript的類有他們對想法(但有創意!) .constructor()方法。

在jQuery的1.6.4(在CoffeeScript的主頁目前使用的),一種無限遞歸在jQuery的本身的246系列創作,在這行代碼:

var ret = this.constructor(); 

this這裏指向你的構造函數,但jQuery希望它指向自己。您的@merge()方法不會正確替換構造函數。還有一個更hackier出路,你@merge()方法更改爲:在「嘗試CoffeeScript中」表示,它的工作原理

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 

休閒的測試,但我很警惕,所以如果你繼續這個奇怪的效果可以在以後顯現方法,通過測試。

+0

它的工作原理!儘管我將構造函數副本添加到構造函數中,以防止它被遞歸調用。我的UIObject構造函數如下所示:'element = jQuery(tag,attributes) @merge(element,this) @constructor = element.constructor' @UIObjectProperties = {} – user1065745