В чем разница между методами javascript, назначенными свойствам «this», и методами, определенными в прототипе? - PullRequest
1 голос
/ 24 марта 2011

Я понимаю, что цель методов, назначаемых в конструкторе как свойства "this", состоит в том, чтобы сделать их привилегированными, так как они могут обращаться к закрытым атрибутам и методам, подобным этому:

var Book = function(newFirst, newLast){

  //private attributes
  var author_first = newFirst;
  var author_last = newLast;

  //public attributes
  this.puAuthor_first = newFirst;
  this.puAuthor_last = newLast;

  //public privileged methods (accessing private attributes)
  this.getAuthor = function()  {
    return author_first + author_last;
  }

}

но в чем отличие от объектов, которые наследуются от Book, по сравнению с методами, назначенными объекту-прототипу, следующим образом:

Book.prototype.nonPrivilegedGetAuthor = function() {
   return this.puAuthor_first + this.puAuthor_last;
} 

Итак, мой вопрос в 2 раза:

1) Когда этот объект наследуется через Prototypical Inheritance, оба getAuthor () и nonPrivilegedGetAuthor () наследуются, верно? И идея состоит в том, что getAuthor () будет скопирован в новый объект, тогда как nonPrivilegedGetAuthor () будет доступен через цепочку прототипов, с преимуществом не копироваться, верно? Каковы затраты, помимо невозможности получить доступ к частным пользователям?

2) А как насчет классического наследования? В частности, будет ли наследоваться общедоступный непривилегированный метод, назначенный в качестве свойства объекта-прототипа? Какие соображения я должен быть обеспокоен там? Не делая еще нескольких вещей, когда вы наследуете, вы в основном будете иметь пробел в цепочке прототипов, который пропускает один объект, верно? Мы должны соединить цепочку прототипов дочернего объекта с Книгой - как мы это делаем? Что мы делаем, чтобы правильно наследовать, и какие подводные камни могут случиться, если мы этого не сделаем?

1 Ответ

3 голосов
/ 12 апреля 2011

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

Что касается наследования, я должен отложить до Дугласа Крокфорда: http://www.crockford.com/javascript/inheritance.html. Что касается того, чтобы сделать переменные закрытыми, нет способа действительно сделать переменную частной в кросс-браузерном режиме, но вы можете притворяться. Я сделал это с цветными объектами jPaq, и другие написали об этом. Еще раз, я бы посоветовал взглянуть на то, что говорит Дуглас Крокфорд: http://www.crockford.com/javascript/private.html. Хотя мой подход немного отличается, если вы хотите сделать членов приватными, это не невозможно в JavaScript. Вот пример того, как реализовать частные переменные кросс-браузерным способом:

var Book = (function() {
  var key = {};

  var Book = function(newFirst, newLast) {
    // Private variables stored in an object literal.
    var $ = {
      author_first : newFirst,
      author_last : newLast
    };

    // Public privileged method for accessing private variables.
    this._ = function(aKey) {
      if(aKey === key)
        return $;
      throw new Error("The _() function must be called internally.");
    };
  };

  // Public accessor method.
  Book.prototype.getAuthor = function() {
    var $ = this._(key);
    return $.author_first + " " + $.author_last;
  };

  return Book;
})();

var bookA = new Book("Chris", "West"),
    bookB = new Book("Douglas", "Crockford");
alert(bookA.getAuthor());
alert(bookB.getAuthor());

Это то же самое, что я реализовал приватные члены в jPaq.

...