В javascript, когда наследование прототипа является более адекватным, чем замыкание для создания объекта? - PullRequest
0 голосов
/ 12 марта 2012

Насколько я понимаю, Prototypal inheritance и closure - два несовместимых способа создания объектов.

  • С прототипами все экземпляры имеют одну и ту же функцию
  • С замыканиями каждый экземпляр имеет свою собственную функцию (со своим конкретным замыканием)

ByСоздавая объект, используя clojure, я имею в виду следующий шаблон:

    function createPerson(p){
           return { 
               getName: function() { return p;} 
           };
    }

Когда при написании приложения Javascript prototype является лучшим выбором, чем closure для создания объектов?Я не ищу общих объяснений о преимуществах prototypal inheritance.Вместо этого я хотел бы увидеть сценарий реальной веб-разработки , где prototype inheritance действительно полезен.

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

Ответы [ 3 ]

3 голосов
/ 12 марта 2012

Вопрос, заданный в этом вопросе, не кажется мне правильным. Замыкания и наследование прототипов - это два разных аспекта языка, они не являются несовместимыми. JS - это язык ООП, основанный на прототипах, а не на классах. Закрытие - это способ сохранить область действия функции за пределами ее выполнения. Я не понимаю, почему они должны быть несовместимыми. Чтобы привести пример, я мог бы иметь что-то вроде этого:

function MyButton(tag) {
   tag.addEventListener("click", this.onClick.bind(this), false);
}

MyButton.prototype = {
   constructor: MyButton,

   onClick : function(event){
       this.doSomething();
   },

   doSomething : function() {
       // do something
   }
}

function MySpecialButton(tag) {
    MyButton.call(this, tag);
}

MySpecialButton.prototype = Object.create(MyButton);

MySpecialButton.prototype.doSomething = function() {
    // do something else
}

Обратите внимание, что с помощью bind я создаю замыкание, более элегантно, где поддерживается ES5. Вы можете получить тот же результат, используя более явное замыкание, если хотите:

function MyButton(tag) {
   var myself = this;
   tag.addEventListener("click", function(event) { myself.onClick(event) }, false);
}

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

1 голос
/ 12 марта 2012

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

1 голос
/ 12 марта 2012

В вашем новом примере вы не «создаете человека».Вместо этого вы возвращаете простой объект js.Опять же, речь идет не о замыкании, а о прототипе, потому что я также могу иметь:

 function createPerson(p){
       return { 
           name : p,
           getName: function() { return this.name } 
       };
}

Это не использует преимущества замыкания, но использует тот же подход для создания экземпляра объекта.Как видите, повторное использование closure не имеет ничего общего с созданием объекта, может использоваться - или нет - вместе, несмотря на то, используете ли вы прототип или нет:

function Person(name) {
    this.getName = this.getName.bind(name);  
}

Person.prototype.getName = function(name) {
    return name;
}

Обычно я этого избегаю, но выможет иметь это.Также:

function Person(name) {
    this.getName = function() { return name };
}

Итак, если ваш вопрос «почему я должен создать объект таким образом, а не простой объект» - это не имеет ничего общего с замыканиями - ответ «потому что тогда вы беретеПреимущество наследования ":

function Mutant(name) {
    Person.call(this, name);
}

Mutant.prototype = Object.create(Person.prototype);

var cyclops = new Mutant("Scott Summers");

alert(cyclops instanceof Person) // true

alert(cyclops instanceof Mutant) // true

alert(cyclops instanceof Object) // true
...