Внедрение переменных частного экземпляра в Javascript
Я не знаю, как я пропустил это так долго. Я предполагал, что частные переменные экземпляра работают так, но они этого не делают. Они частные (как в неглобальных), конечно, но переменные разделяются между экземплярами. Это привело к некоторым очень запутывающим ошибкам.
Я думал, что я слежу за лучшими практиками, реализованными некоторыми из лучших библиотек, но, похоже, я что-то пропустил.
var Printer = (function(){
var _word;
Printer = function(word){
_word = word;
}
_print = function(){
console.log(_word);
}
Printer.prototype = {
print: _print
}
return Printer;
})();
var a = new Printer("Alex");
var b = new Printer("Bob");
a.print(); //Prints Bob (!)
b.print(); //Prints Bob
Я просмотрел этот пост, но он не описывает наилучшую практику для реализации частных переменных экземпляра. (это даже название того, что я хочу?)
Метод и изменение переменных частных переменных и экземпляров в JavaScript
Я также просмотрел этот пост, но использование ключевого слова 'this' - это то, что я делал. Потому что это не запутывает, я пытался избежать этого. Это действительно единственный способ?
Внедрение методов/переменных экземпляра в прототипальном наследовании
Ответы
Ответ 1
Вы делаете некоторые неуклюжие вещи с этим закрытием. _word
должен быть объявлен в функции Printer
, а не потерян в зоне анонимного закрытия:
function Printer(word) {
var _word = word;
this.print = function () {
console.log(_word);
}
}
var a = new Printer("Alex");
var b = new Printer("Bob");
a.print(); //Prints Alex
b.print(); //Prints Bob
Это сохраняет _word
private, за счет создания новой функции print
на каждом экземпляре Printer
. Чтобы сократить эту стоимость, вы открываете _word
и используете одну прототипную функцию print
:
function Printer(word) {
this._word = word;
}
Printer.prototype.print = function () {
console.log(this._word);
}
var a = new Printer("Alex");
var b = new Printer("Bob");
a.print(); //Prints Alex
b.print(); //Prints Bob
Действительно ли имеет значение, что _word
отображается? Лично я так не думаю, особенно учитывая префикс _
.
Ответ 2
Приватные затраты дороги, избегайте их, если это возможно
Частное не существует. Вы можете сделать одну из двух вещей, чтобы подражать этому.
Затворы
function makePrinter(word) {
return {
print: function () {
console.log(word)
}
}
}
WeakMap
Поддержка браузера для слабых карт ужасна. Возможно, вам понадобится эмуляция, я рекомендую pd.Name
var Printer = (function () {
var privates = function (obj) {
var v = map.get(obj)
if (v === undefined) {
v = {}
map.set(obj, v)
}
return v
}, map = new WeakMap()
return {
constructor: function (word) {
privates(this).word = word
},
print: function () {
console.log(privates(this).word)
}
}
}());
Чувствительные объекты
var Printer = {
constructor: function (word) {
this._word = word
},
print: function () {
console.log(this._word)
}
}
Ответ 3
Небольшая модификация кода с использованием this
будет работать. Правильный экземпляр Printer.prototype.print
не был создан для объекта a
.
var Printer = (function(){
var _word;
Printer = function(word){
this._word = word;
}
_print = function(){
console.log(this._word);
}
Printer.prototype = {
print: _print
}
return Printer;
})();
var a = new Printer("Alex");
var b = new Printer("Bob");
a.print(); //Prints Alex
b.print(); //Prints Bob