Can I “extend” a closure-defined “class” in Javascript?

I have a Javascript "class" defined like so:

var Welcomer = function(name) {
  var pName = name;
  var pMessage = function() {
    return "Hi, " + pName + "!";
  };

  return {
    sayHi: function() {
      alert(pMessage());
    }
  };
};

new Welcomer('Sue').sayHi();

Is there a way to "subclass" Welcomer in such a way that I can redefine the public methods and have access to the private methods and variables? The following will give me access to the public methods, but not to the private ones:

var UnhappyWelcomer = function(name) {
  var pSadMessage = function() {
    // won't work, b/c I don't have access to pMessage
    return pMessage() + " Miserable day, innit?";
  };

  return {
    sayHi: function() {
      alert(pSadMessage());
    }
  };
};
UnhappyWelcomer.prototype = Welcomer(); // failed attempt at inheritance

new UnhappyWelcomer().sayHi();
15
задан James A. Rosen 24 August 2010 в 21:32
поделиться

3 ответа

Простой ответ на ваш вопрос: Нет .

Вы не можете ничего сделать, чтобы получить доступ к тем вещам, которые определены var , если только ваша функция не находится в той же области действия, или вы каким-то образом «сделаете общедоступным» информацию (вернув ее или установив ее на , это ).

Если у вас есть доступ для редактирования исходной функции, вы можете переписать вещи таким образом, чтобы эти функции могли быть «переданы» в расширяющую функцию, которая может изменять «защищенную» область действия объекта. Следующий код должен дать хорошее представление о том, что я предлагаю.

var Welcomer = function(name) {
  var _protected = {
    name: name,
    message: function() {
      return "Hi, " + _protected.name + "!";
    }
  };

  return {
    extendWith: function(extender) {
      extender.call(this, _protected);
      return this;
    },
    sayHi: function() {
      alert(_protected.message());
    }
  };
};

var UnhappyWelcomer = function(name) {
  var self = Welcomer(name).extendWith(function(_protected) {
    _protected.sadMessage = function() {
       return _protected.message() + " Miserable day, innit?";
    };
    // extending the public while still having scope to _protected...
    this.sayHi = function() {
      alert(_protected.sadMessage());
    };
  });
  return self;
};

UnhappyWelcomer('bob').sayHi();
9
ответ дан 1 December 2019 в 04:00
поделиться

Если вам действительно нужно наследование, есть несколько библиотек, которые очень помогут. Одним из вариантов является trait.js, который в любом случае может стать стандартной частью javascript в какой-то момент. Если вас это не устраивает, у таких библиотек, как jQuery и прототип, есть помощники для наследования.

Если вы хотите использовать минимальный подход с нуля, я настоятельно рекомендую вам использовать модель прототипа для всего. Вы увидите значительное увеличение производительности по сравнению с шаблоном, который у вас есть в ваших примерах.

Чтобы более точно ответить на ваш вопрос, нет. Вам будет легче, если вы создадите свои «классы», чтобы не полагаться на частные функции.

1
ответ дан 1 December 2019 в 04:00
поделиться

Этот шаблон "класса" не является шаблоном "класса", он известен как Модульный шаблон. Он возвращает объект, который не имеет никакой связи с функцией, создавшей его, кроме доступности его частных переменных. Возвращенный объект НЕ является экземпляром функции, которая его создала.

Когда вы вызываете 'new Class()', он создает экземпляр этой функции, но также возвращает другой объект. Любые дальнейшие операции фактически выполняются с возвращаемым объектом, а не с экземпляром.

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

Дополнительная литература:

Извините, что оставляю вам материал для чтения, но мне кажется, что вы изучаете возможности. Эти статьи дадут более глубокое понимание этого вопроса.

Как только вы узнаете больше об этом вопросе, вы, скорее всего, вообще проигнорируете приватные члены и будете использовать префикс _ и просто сделаете его общедоступным, как и все остальные ;) Просто это проще, а приватные члены в любом случае бессмысленны.

8
ответ дан 1 December 2019 в 04:00
поделиться
Другие вопросы по тегам:

Похожие вопросы: