Подтвердить что ты не робот

Javascript: class.property vs class.prototype.property для эмуляции статических свойств

Я пытаюсь подражать статическим свойствам в javascript. В нескольких местах упоминалось, что class.prototype.property будет статическим по всем объектам, наследующим от класса. Но мой POC говорит иначе. Пожалуйста, посмотрите:

Использование класса 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*/

Мой вопроС# 1: Если это должно быть статичным, то не должно быть значения count 4,5,6 и т.д., так как все объекты имеют одну и ту же переменную счета?

Затем я сделал еще один POC с Class.prototype, и я думаю, что это статично.

Использование класса 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*/

Мой вопрос №2: Нигде я не видел, как class.property используется напрямую. Как именно статические переменные сделаны в javascript, имея в виду мой вышеприведенный код?

Или я закодировал здесь что-то не так? Это не правильное восприятие?

4b9b3361

Ответ 1

Мой вопроС# 1: Если это должно быть статичным, то не должно быть значения count 4,5,6 и т.д., так как все объекты имеют одну и ту же переменную счета?

Свойства прототипа разделяются между экземплярами, но если экземпляр имеет свою собственную копию свойства, он будет использовать это вместо этого. Присвоение свойства экземпляру дает ему свою собственную копию, и поэтому он больше не использует прототип.

+=, ++ и аналогичные операторы приводят к назначению, поэтому они также вызывают это поведение.

Рассмотрим:

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

Как и в предыдущем коде, для Employee.prototype имеется объект в памяти. Некоторое искусство ASCII:

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

Затем мы делаем следующее:

var e = new Employee();

Теперь есть второй объект в памяти, который ссылается на Employee.prototype:

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

И если вы запросите e.count:

console.log(e.count);

... так как e не имеет собственного свойства, называемого count, движок ищет прототип e, чтобы найти его, найти и использовать это значение.

Однако, когда мы это делаем:

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

Это присваивает значение count в экземпляре e. e теперь имеет свою собственную копию count:

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

Теперь, если вы запросите e.count:

console.log(e.count);

... движок находит count на e и не смотрит на прототип.

Этот эффект можно увидеть в коде:

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