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

Внедрение переменных частного экземпляра в 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' - это то, что я делал. Потому что это не запутывает, я пытался избежать этого. Это действительно единственный способ? Внедрение методов/переменных экземпляра в прототипальном наследовании

4b9b3361

Ответ 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

Приватные затраты дороги, избегайте их, если это возможно

Частное не существует. Вы можете сделать одну из двух вещей, чтобы подражать этому.

  • закрытие
  • Weakmaps

Затворы

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