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:
Dokładnie tak, jak to zrobiłeś, Employee.sharedProperty
.
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
używać drugiej formy cały czas. – tjameson
Myślę, że 'this' jest zawsze ** instancją ** wskazuje na _zdefiniowany przez obiekt_czasu_czasu, podczas gdy' Employee' w twoim kodzie jest "deklaracją prototypową". – Passerby