2009-08-11 13 views
8

Chciałem zapytać o plusy tego mojego stylu OOP. Piszę moje klasy JS w następujący sposób.Czy to dobry sposób na wykonanie 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"); 

Czy to dobre podejście? Czy jest jakaś wada? Nie używam dziedziczenia, ale czy działałoby to w ten sposób, aby osiągnąć dziedzictwo?

Z góry dziękuję.

Odpowiedz

6

Myślę, że to bardzo dobre podejście. Nie wstydź się kwestii "nie ma dziedzictwa". Większość OOP nie dotyczy dziedziczenia. Najważniejszymi aspektami są enkapsulacja i polimorfizm, a ty je masz.

Można argumentować (no, zwykle twierdzę), że dziedziczenie jest potrzebne tylko dla języków statycznych, gdzie trzeba jakoś powiedzieć kompilatorowi, że te dwa typy (klasy) są ze sobą powiązane, że mają coś wspólnego (wspólny przodek), aby umożliwić polimorfizm. Dzięki dynamicznym językom, OTOH, kompilator nie będzie się tym przejmował, a środowisko uruchomieniowe znajdzie podobieństwa bez dziedziczenia.

Kolejny punkt: jeśli potrzebujesz jakiegoś dziedziczenia w niektórych miejscach (i na przykład w niektórych przypadkach jest to świetna, np. GUI), często przekonasz się, że możesz łatwo współdziałać pomiędzy "prostymi" obiektami/klasami i inne bardziej złożone i cięższe. IOW: nie próbuj znaleźć ramy, która zaspokoi wszystkie twoje potrzeby i wykorzystaj ją do wszystkiego; zamiast tego korzystaj z tego, który jest ci wygodniejszy w każdej chwili, o ile pomaga w rozwiązywaniu określonego problemu.

+0

+1 za - Najważniejsze aspekty to enkapsulacja i polimorfizm. – Everyone

+0

+1 także tutaj. Dziedzictwo z pewnością ma zbyt dużą wagę w wielu artykułach dotyczących OO. Właśnie zacząłem programować w OO produktywnie przez ostatnie kilka lat, a ja już straciłem rachubę moich błędów początkujących spowodowanych przez nadmierne poleganie na dziedziczeniu. –

2

Faktycznie, to nie różni się od sposobu, w jaki Prototype.js (moja ulubiona biblioteka) ogólnie to robi. Jeśli spojrzysz tutaj:

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 
    } 
    }; 
})(); 

Zaletą powyższego jest to, że będziesz w stanie zarządzać dziedzictwem szybko i łatwo. W twoim przypadku dziedziczenie (lub przynajmniej nadrzędne funkcje) jest prawie niemożliwe bez tworzenia jakiejś formy zewnętrznej funkcji pomocnika, jak wyżej.

0

Jeśli szukasz struktury dziedziczenia opartej na większej liczbie klas w kodzie JavaScript, sprawdź numer Dojo.

0

Możesz także użyć literałów i budowniczych.W ten sposób nie musisz korzystać z mniej atrakcyjnych pojęć w JavaScript: prototype, new-statement i this-keyword.

Podstawowym recepta jest prosta:

  • utworzyć funkcję, która buduje dosłownym obiektowi
  • umieścić, że funkcjonują w dosłownym obiektu

dosłownym, który ma aktów konstruktora jako klasa . Funkcje konstruktora działają jako konstruktor, a produkowany język działa jako instancja klasy.

Oto przykład:

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(); 

Więcej docs można znaleźć tutaj:

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

a tu

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

Powiązane problemy