2012-11-21 8 views
11

Próbowałem emulować właściwości statyczne w javascript. W kilku miejscach wspomniano, że klasa.prototype.property będzie statyczna dla wszystkich obiektów dziedziczących po klasie. Ale mój POC mówi inaczej. Proszę spojrzeć:javascript: class.property vs class.prototype.property na emulowanie właściwości statycznych

Korzystanie Class.prototype.property

//Employee class 
function Employee() { 
    this.getCount = function(){ 
     return this.count; 
    };  
    this.count += 1; 
} 
Employee.prototype.count = 3; 

var emp = [], i; 
for (i = 0; i < 3; i++) { 
    emp[i] = new Employee(); 
    console.log("employee count is "+ emp[i].getCount()); 
} 
/*Output is: 
employee count is 4 
employee count is 4 
employee count is 4*/ 

Moja Pytanie # 1: Jeżeli miałoby to być statyczny, a następnie nie powinno wartość licznika została 4,5 , 6 itd., Ponieważ wszystkie obiekty mają tę samą zmienną licznika?

Potem zrobiłem kolejny POC z Class.prototype i myślę, że to jest statyczne.

Korzystanie Class.property

//Employee class 
function Employee() { 
    this.getCount = function(){ 
     return Employee.count; 
    };  
    Employee.count++; 
} 
Employee.count = 3; 

var emp = [], i; 
for (i = 0; i < 3; i++) { 
    emp[i] = new Employee(); 
    console.log("employee count is "+ emp[i].getCount()); 
} 
/*Output is: 
employee count is 4 
employee count is 5 
employee count is 6*/ 

Moje pytanie nr 2: Nigdzie nie widziałem class.property wykorzystywane bezpośrednio. Jak dokładnie są zmienne statyczne wykonane w javascriptu pamiętając powyższy kod?

Czy coś tu zapisałem? Czy to nie jest prawidłowe postrzeganie?

+2

używać drugiej formy cały czas. – tjameson

+0

Myślę, że 'this' jest zawsze ** instancją ** wskazuje na _zdefiniowany przez obiekt_czasu_czasu, podczas gdy' Employee' w twoim kodzie jest "deklaracją prototypową". – Passerby

Odpowiedz

30

Moje pytanie nr 1: Jeśli miałoby to być statyczne, to czy wartość licznika nie powinna być 4,5,6, itd., Ponieważ wszystkie obiekty mają tę samą zmienną licznika?

Własności prototypów są współużytkowane w różnych instancjach, ale jeśli instancja ma własną kopię właściwości, będzie jej używać. Przypisanie do właściwości instancji daje jej własną kopię, więc nie używa już prototypów.

The +=, ++ i podobne operatory skutkują przypisaniami, a więc również powodują takie zachowanie.

Rozważmy:

function Employee() { 
} 
Employee.prototype.count = 0; 

Jak z powyższego kodu, istnieje obiekt w pamięci Employee.prototype. Niektóre ASCII Art:

+−−−−−−−−−−−−−−−−−−−−+ 
| Employee.prototype | 
+−−−−−−−−−−−−−−−−−−−−+ 
| count: 0   | 
+−−−−−−−−−−−−−−−−−−−−+

Potem robimy to:

var e = new Employee(); 

Teraz jest drugi obiekt w pamięci, która zawiera odesłanie do Employee.prototype:

+−−−−−−−−−−−−−−−+ 
|  e   | 
+−−−−−−−−−−−−−−−+   +−−−−−−−−−−−−−−−−−−−−+ 
| [[Prototype]] |−−−−−−−−−>| Employee.prototype | 
+−−−−−−−−−−−−−−−+   +−−−−−−−−−−−−−−−−−−−−+ 
          | count: 0   | 
          +−−−−−−−−−−−−−−−−−−−−+

A jeśli kwerendy e.count:

console.log(e.count); 

... ponieważ e nie ma własnej właściwości o nazwie count, silnik sprawdza prototyp e, aby go znaleźć, znajduje i używa tej wartości.

Jednak, kiedy to zrobić:

e.count += 1; // Or more idiomatically, `++e.count;` or `e.count++;` 

To przypisuje wartość do count na przykład e. e ma teraz swój własnykopię count:

+−−−−−−−−−−−−−−−+ 
|  e   | 
+−−−−−−−−−−−−−−−+ 
| count: 1  |   +−−−−−−−−−−−−−−−−−−−−+ 
| [[Prototype]] |−−−−−−−−−>| Employee.prototype | 
+−−−−−−−−−−−−−−−+   +−−−−−−−−−−−−−−−−−−−−+ 
          | count: 0   | 
          +−−−−−−−−−−−−−−−−−−−−+

Teraz jeśli kwerendy e.count:

console.log(e.count); 

... silnik znajdzie count na e i nie patrzeć na prototyp.

Można zobaczyć ten efekt w postaci kodu:

function Employee() { 
 
} 
 
Employee.prototype.count = 0; 
 

 
var e = new Employee(); 
 
console.log(e.hasOwnProperty('count')); // false 
 
e.count += 1; 
 
console.log(e.hasOwnProperty('count')); // true 
 

 
console.log(e.count);     // 1 
 
console.log(Employee.prototype.count); // 0

Jest to również zabawa:

var e = new Employee(); 
 

 
console.log(e.count);     // 0 
 
++Employee.prototype.count; 
 
console.log(e.count);     // 1

Od e nie ma jeszcze własnej kopii count, jeśli faktycznie zwiększy się wartość nieruchomości na Employee.prototype, widzimy zaktualizowaną wartość, czy prosimy o nią bezpośrednio (Employee.prototype.count) lub pośrednio ().

Ostatnia uwaga na to: Jeżeli e dostaje własną kopię nieruchomości, można go usunąć ponownie:

var e = new Employee(); 
 
console.log(e.count); // 0, because it's using `Employee.prototype.count` 
 
++e.count;    // Now `e` has its own `count` property 
 
console.log(e.count); // 1, `e`'s own `count` 
 
delete e.count;   // Now `e` doesn't have a `count` property anymore 
 
console.log(e.count); // 0, we're back to using `Employee.prototype.count`

delete byłyby bardziej prawidłowo zwany remove. Usuwa właściwości z obiektów.

Moje pytanie nr 2: Nigdzie nie widziałem, aby klasa.property była używana bezpośrednio. Jak dokładnie są zmienne statyczne wykonane w javascriptu pamiętając powyższy kod?

dwa sposoby:

  1. Dokładnie tak, jak to zrobiłeś, Employee.sharedProperty.

  2. Definiując całą „klasę” wewnątrz funkcji, a przy użyciu zmiennych lokalnych wewnątrz tej funkcji:

    var Employee = (function() { 
        var sharedVariable = 0; 
    
        function Employee() { 
         ++sharedVariable; 
         console.log("sharedVariable = " + sharedVariable); 
        } 
    
        return Employee; 
    })(); 
    

    Wszystkie funkcje określone w tym zewnętrznej funkcji określania zakresu będą mieli dostęp do zmiennych lokalnych zdefiniowanych w nim. Jest więc tylko jedna zmienna, lokalna w ramach jednego wywołania tej zewnętrznej funkcji, która tworzy Employee.

    Następnie ten kod:

    new Employee(); 
    new Employee(); 
    new Employee(); 
    new Employee(); 
    

    wyjścia

    1 
    2 
    3 
    4
+0

Dziękuję za to dokładne wyjaśnienie. Byłem w dużym zamieszaniu, gdy zobaczyłem, że właściwości statyczne można wprowadzić w javascriptie przez prototoype.properties, a mój kod zrobił inaczej. – riju

+0

Dziękuję za to dokładne wyjaśnienie. Tak więc, w zasadzie Class.prototype.properties jest statyczny, w tym przypadku zmienia się tylko właściwości object.properties. Gdybym zamiast tego zrobił Employee.prototype.count + = 1, działałby zgodnie z oczekiwaniami. Tak więc dla pewnej statycznej implementacji właściwości, sugerujesz, żebym podał mój drugi kod lub drugi sposób implementacji, o którym wspomniałeś. Dzięki jeszcze raz. – riju

+1

@riju: Tak czy inaczej, to zależy od ciebie. To zależy od tego, jak publiczne mają być te informacje. Jeśli użyjesz 'Employee.count', a' Employee' jest publiczne, to 'Employee.count' jest publiczne - każdy kod w dowolnym miejscu może go zaktualizować. Które mogą być przydatne. Jeśli używasz wzorca modułu (mój drugi przykład), tylko kod w tej zewnętrznej funkcji zakresu ma dostęp do 'sharedVariable'. W efekcie jest to prywatny kod "Employee" zdefiniowany przez Ciebie. Możesz dodać funkcje do 'Employee.prototype' i tak długo, jak robisz to w ramach funkcji scoping, mogą używać' sharedVariable' (ale inni nie mogą). –

Powiązane problemy