2016-03-29 5 views
1

Мне нужен конструктор, который инициализирует Objects с уникальным name. Я пишу код, как это:Статическое личное поле Javascript

Obj.prototype.idCounter = 0; 
Obj = function() { 
    this.name = "Obj_" + Obj.prototype.idCounter; 
    Obj.prototype.idCounter++; 
} 

var o1 = new Obj(); 
var o2 = new Obj(); 
alert(o1.name); // Obj_0 
alert(o2.name); // Obj_1 

Но Obj.prototype.idCounter не является частным. Я знаю, как создать приватную переменную, но я понятия не имею, как создать приватную статическую переменную.

+1

Ну, дело в том, что javascript не может быть сопоставлен с классическим объектно-ориентированным языком, он прототип ориентирован. Короткий ответ: извините, но вы не можете. – axelduch

+0

Введение функции Symbol позволит создать более надежный код против угрозы * случайных * конфликтов свойств, но по-прежнему невозможно по-настоящему скрыть свойства объекта благодаря 'Object.getOwnPropertyNames()' и ' Object.getOwnPropertySymbols() '. Для некоторых целей вы можете использовать закрытие. – Pointy

+0

Привет, просто пытаюсь узнать здесь. Является закрытием, как вы создадите приватную переменную, и мы говорим, что сделать эту приватную переменную static невозможно в js? – Observer

ответ

3

Что вы можете сделать это:

var Obj = function() { 
    var idCounter = 0; 

    function Obj() { 
     this.name = "Obj_" + idCounter; 
     idCounter++; 
    } 
    return Obj; 
}(); 

Теперь idCounter является локальной переменной в этой анонимной функции, так что ничего не может видеть его функции конструктора, за исключением.

Обратите внимание, что вы можете также сделать некоторые инициализации объекта-прототипа там тоже:

var Obj = function() { 
    var idCounter = 0; 

    function Obj() { 
     this.name = "Obj_" + idCounter; 
     idCounter++; 
    } 
    // one way to add a prototype property, and not 
    // the simplest 
    Object.defineProperties(Obj.prototype, { 
     getInstanceCount: { 
     value: function() { 
      return idCounter; 
     } 
     } 
    }); 
    return Obj; 
}(); 

Теперь, когда у вас есть экземпляр Obj вы можете позвонить getInstanceCount(), чтобы получить общее количество объектов, созданных (которые бы быть странным способом разработки API, но просто для иллюстрации того, что функции прототипа могут также получить доступ к этим частным переменным).

+1

@axelduch no do not - приятно иметь альтернативные версии. – Pointy

+0

Почему вы используете 'Object.defineProperties' для назначения простого метода? – Bergi

+0

@Bergi Так рад, что ты спросил! :) Я пытался привыкнуть к определению прототипов функций по нескольким причинам, в основном для того, чтобы сделать * продление * прототипов менее странным, но также сохранить собственные свойства (например, через 'Object.keys() '). Это личная аффектация, но дело в том, что я действительно не очень много думал об этом, когда набирал этот код, поэтому это означает, что самообъявление, которое я пытался, по-видимому, сработало. – Pointy

3

Невозможно (насколько я знаю) реплицировать частные статические элементы так, как вы его описали.

Что вы можете сделать, чтобы решить проблему безопасности вашего генератора id, - использовать шаблон модуля и использовать для него привилегированный доступ из области видимости модуля.

// using an immediately invoked function to generate the isolated scope 
var Obj = (function() { 
    var idCounter = 0; 

    return function Obj() { 
     this.name = "Obj_" + idCounter; 
     idCounter++; 
    }; 
}()); 

var o1 = new Obj(); 
var o2 = new Obj(); 
alert(o1.name); // Obj_0 
alert(o2.name); // Obj_1 
0

В JavaScript, вы, как правило, префикс имен полей с подчеркиванием _ указывают, что они являются частными. Конечно, это не делает их действительно частными, но разработчики должны демонстрировать некоторую самодисциплину и считать ее закрытой.

function Obj() { 
 
    this.name = "Obj_" + (Obj._idCounter++); 
 
} 
 
Obj._idCounter = 0; 
 

 
var o1 = new Obj(); 
 
var o2 = new Obj(); 
 
log(o1.name); // Obj_0 
 
log(o2.name); // Obj_1 
 

 
function log(x) { var p = document.createElement('pre'); p.appendChild(document.createTextNode(x)); document.body.appendChild(p); }

Если вы действительно хотите, чтобы скрыть то, что вы можете закрытий использования курса, как и другие заявили. Однако это немного сложнее для отладки и по какой-то причине является bit slower.

Смежные вопросы