Могу ли я "расширить" определенный классом закрытия в Javascript? - PullRequest
15 голосов
/ 25 августа 2010

У меня есть класс Javascript, определенный следующим образом:

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

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

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

Есть ли способ "подкласса" Welcomer таким образом, чтобы я мог переопределить публичные методы и получить доступ кприватные методы и переменные?Следующее даст мне доступ к общедоступным методам, но не к частным:

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();

Ответы [ 3 ]

9 голосов
/ 25 августа 2010

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

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

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

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();
8 голосов
/ 25 августа 2010

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

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

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

Дополнительные сведения:

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

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

1 голос
/ 25 августа 2010

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

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

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

...