2011-05-13 10 views
6

Jestem nowicjuszem w JavaScript i próbuję zrozumieć, w jaki sposób powinienem pisać klasy (moje tło w "zwykłych" językach OO, takich jak java i C++).Prawidłowy sposób na tworzenie klas w JavaScript?

Rozumiem, że mam dwie opcje:

  1. jeśli chcę mieć moja klasa metod prywatnych oraz członków i nie może definiować je w prototypie. Ale w takim przypadku zostaną one zbudowane dla każdego nowo utworzonego obiektu (problem z pamięcią).

  2. Jeśli zdefiniuję metody w prototypie klasy, nie będę zawierał enkapsulacji (jest to dla mnie dziwne, jako programisty java/C++: P).

Którą z dwóch metod używasz? czemu?

+0

przeczytać tutaj: http://www.crockford.com/javascript/inheritance.html –

+0

Również w tym: http://javascript.crockford.com/ private.html –

+0

Zapoznaj się z [Podstawy OOP] (http://stackoverflow.com/questions/5134208/jquery-oop-basics/5134494#5134494) – Raynos

Odpowiedz

7

Nie sądzę, że istnieje "odpowiednia odpowiedź" na to pytanie ... w zasadzie to, co preferujesz, jest dla Ciebie najlepsze. Wiele z moich zajęć to "klasy statyczne", np.

var MyClassName = { 
    methodName: function() { }, 
    //... 
} 

Ponieważ nigdy nie muszę ich tworzyć. Kiedy potrzebuję utworzyć instancję wielu instancji, używam metody prototypowej.

Jeśli potrzebujesz zmiennych prywatnych, możesz zdefiniować funkcję/klasę do robienia zmiennych prywatnych i metody, które muszą uzyskać dostęp do prywatnych zmiennych wewnątrz tej funkcji/klasy. Następnie użyj metody prototypowej dla wszystkich metod, które nie wymagają dostępu do prywatnych zmiennych. Na przykład.

var PageClass = function() { 
    var _birthdate; 

    this.getBirthdate = function() { 
     return typeof(_birthdate) == "undefined" ? null : _birthdate; 
    } 
    this.setBirthdate = function(date) { 
     if(typeof(date) == 'object' && date.constructor == Date) { 
      _birthdate = date; 
     } 
     else { 
      throw "Invalid Argument Exception: PageClass.setBirthdate expects parameter of type 'Date'"; 
     } 
    } 
} 
PageClass.prototype.doSomething = function() { 
    alert("DOING SOMETHING"); 
} 

Wykonanie obu zadań powinno umożliwić zachowanie nieco mniejszej wagi, ale nadal zapewnia pewną enkapsulację. Do tej pory nigdy nie zawracałem sobie głowy prywatnymi podwładnymi.

0

Jeśli korzystasz z platformy prototypowej, lepiej będzie, jeśli wykorzystasz sposób implementacji klas i dziedziczenia. Prawdopodobnie odnosiłeś się do this article

Zazwyczaj nie sądzę, że członkowie prywatni są używani w javascript. (edit. Nie w klasach instancja widzę dość regularnie kilka „modułów” w naszym kodzie, które posiadają prywatny stan, ale mogłoby być postrzegane jako pojedynczych)

Kevina odpowiedź prawie podsumowuje to. Jest technicznie możliwe obejście problemu braku enkapsulacji języka, ale wiąże się to z kosztem, jeśli twoja klasa będzie często tworzona. Myślę też, że potrzebujesz trochę pracy, aby uzyskać ochronę widoczności, jeśli zamierzasz używać dziedziczenia.

Nie sądzę, że widziałem żadnych prywatnych rzeczy, patrząc na przykład na źródła zewnętrzne. Umieszczają "// prywatny" nad metodami, które powinny być prywatne, co jest wskazówką, że nie powinny być wywoływane bezpośrednio. To znaczy, że potrzebujesz więcej "dyscypliny", aby pisać osoby pobierające/ustawiające, jeśli zamierzasz kodować w ten sposób.

0

Dlaczego tak jest ... teraz.

Powyższe odpowiedzi są poprawne dla ich czasu.

Oto nowy rozwiązanie:

'use strict'; 

// Declare our class 
class Metadata { 

    // Declare the constructor and pass it some values - a and b are "defaults" 
    constructor(ninfo, a = 1.0, b = 1.0) 
    { 
     // Set our class variables 
     this.ninfo = ninfo; 
     this.a = a; 
     this.b = b; 

     // Define our "secret" or nonenumerable options 
     Object.defineProperty(this, 'addA', { 
      enumerable: false, 
      writable: false, 

      // Have it add our passed in value 
      value: n => this.a += n 
     }); 
    } 
} 

// Call our class and pass in some variables 
let x = new Metadata("we have a and b", 1.0); 

// Log our result if we call "addA" 
console.log(x.addA(3)); // => 4 

// Log our object 
console.log(x); // => Metadata { ninfo: 'we have a and b', a: 4, b: 2 } 

// Log our object 'for real' 
console.log(require('util').inspect(x, { showHidden: true, depth: null })); 

// result 
// Metadata { 
//  ninfo: 'we have a and b', 
//  a: 4, 
//  b: 2, 
//  [addA]: { [Function: value] [length]: 1, [name]: 'value' } } 
Powiązane problemy