2009-08-11 145 views
8

我想問一下我的以下OOP風格的優點。 我以下面的方式編寫我的JS類。這是做JS OOP的好方法嗎?

var MyClass = function() { 
    // private vars 
    var self = this, 
     _foo = 1, 
     _bar = "test"; 

    // public vars 
    this.cool = true; 

    // private methods 
    var initialize = function(a, b) { 
     // initialize everything 
    }; 

    var doSomething = function() { 
     var test = 34; 
     _foo = cool; 
    }; 

    // public methods 
    this.startRequest = function() { 

    }; 

    // call the constructor 
    initialize.apply(this, arguments); 
}; 

var instance_1 = new MyClass(); 
var instance_2 = new MyClass("just", "testing"); 

這是一個好方法嗎?有什麼缺點嗎? 我不使用繼承,但它會以這種方式實現繼承嗎?

在此先感謝。

回答

6

我認爲這是一個非常好的方法。不要爲'不傳承'問題感到羞恥。大多數面向對象不是關於繼承。最重要的方面是封裝和多態,你已經得到了它們。 (可以,我經常說)只有靜態語言需要繼承,你必須告訴編譯器這兩種類型(類)是相關的,他們有一些共同的東西(共同的祖先),以便它可以允許多態性。使用動態語言OTOH,編譯器不會在意,運行時環境將找到沒有任何繼承的共同點。另一點:如果您在某些地方需要繼承(例如,在某些情況下,它的編號爲,那麼例如像GUI一樣),但通常您會發現可以輕鬆地在「簡單」對象/類之間進行互操作,其他更復雜和更重。 IOW:不要試圖找到滿足您所有需求並將其用於一切的框架;而是使用你在任何時刻都更加適應的方法,只要它能幫助解決特定的問題。

+0

+1 - 最重要的方面是封裝和多態性。 – Everyone 2009-08-13 09:09:04

+0

也在這裏。在面向對象的許多文章中,繼承肯定是過分的重量。在過去的幾年中,我剛剛開始有成效地開展OO編程,並且我已經失去了因過度依賴繼承而導致的新手錯誤的數量。 – 2011-07-11 01:57:45

2

其實,這與Prototype.js(我最喜歡的庫)通常做的不一樣。如果你看這裏:

var Class = (function() { 
    function subclass() {}; 

    // All classes are created through Class.create({/*JSON Object*/}); 
    // or Class.create(function, ...properties); 
    // The first form will create a unique class. 
    // The second form will create a Class which subclasses the initial function. 
    function create() { 

    var parent = null, 
        // $A just normalizes the array. 
     properties = $A(arguments); 

    // Which type of class definition was used? 
    if (Object.isFunction(properties[0])) 
     parent = properties.shift(); 

    // This effectively creates a constructor 
    function klass() { 
     this.initialize.apply(this, arguments); 
    } 

    // Allows klass to have addMethods property 
    Object.extend(klass, Class.Methods); 
    klass.superclass = parent; 
    klass.subclasses = []; 

    // Does this class have a parent class? 
    if (parent) { 
     subclass.prototype = parent.prototype; 
     klass.prototype = new subclass; 
     parent.subclasses.push(klass); 
    } 

    // Add methods to the class 
    for (var i = 0; i < properties.length; i++) 
     klass.addMethods(properties[i]); 

    // emptyFunction = function(){}; 
    if (!klass.prototype.initialize) 
     klass.prototype.initialize = Prototype.emptyFunction; 

    // Creates the constructor 
    klass.prototype.constructor = klass; 
    return klass; 
    } 

    function addMethods(source) { 
    // Does this class have a parent? 
    var ancestor = this.superclass && this.superclass.prototype; 

    // Grab the keys of a JSON object 
    var properties = Object.keys(source); 

    // Makes sure each object has a toString and valueOf method. 
    if (!Object.keys({ toString: true }).length) { 
     if (source.toString != Object.prototype.toString) 
     properties.push("toString"); 
     if (source.valueOf != Object.prototype.valueOf) 
     properties.push("valueOf"); 
    } 

    //Loop through the properties. 
    for (var i = 0, length = properties.length; i < length; i++) { 

     // property is the Key in the JSON, value is the corresponding 
     // method or property value. 
     var property = properties[i], value = source[property]; 
     if (ancestor && Object.isFunction(value) && 
      value.argumentNames().first() == "$super") { 

     // Handles an override of a parent method. 
     var method = value; 
     value = (function(m) { 
      return function() { return ancestor[m].apply(this, arguments); }; 
     })(property).wrap(method); 

     value.valueOf = method.valueOf.bind(method); 
     value.toString = method.toString.bind(method); 
     } 
     this.prototype[property] = value; 
    } 

    return this; 
    } 

    // And here is the final value! 
    return { 
    create: create, 
    Methods: { 
     addMethods: addMethods 
    } 
    }; 
})(); 

上面的好處是,你將能夠快速,輕鬆地管理繼承。在你的情況下,如果不像上面那樣創建某種形式的外部幫助函數,繼承(或至少重寫函數)幾乎是不可能的。

0

如果您想在JavaScript中尋找更多基於類的繼承結構,您可能需要查看Dojo

0

你也可以使用文字和建設者。通過這種方式,您不必在Javascript中使用不太吸引人的概念:原型,新語句和this關鍵字。

的基本配方很簡單:

  • 創建生成一個文本對象
  • 提出,在一個文本對象

字面具有建設者作爲一類功能的功能。構建器函數充當構造函數,並且生成的文字充當類實例。

下面是一個例子:

Car = { 
    createNew:function() { //no prototype! 
     var obj = {}; 
     var color; 
     obj.setColor = function(c) { color = c; } 
     obj.drive = function(){ alert('driving a '+color+' car'); } 
     return obj; //no this-keyword! 
    } 
} 

var car = Car.createNew(); //no new statement! 
car.setColor('red'); 
car.drive(); 

更多文檔可以在這裏找到:

http://www.gabordemooij.com/jsoop.html

這裏

https://github.com/schuttelaar/Rococo2/wiki/Getting-started