2013-05-28 4 views
3

Имея родительский класс:унаследуют прототип

function Animal() { 
    // do something 
} 

Animal.prototype.walk = function() { 
    alert('I am walking.'); 
}; 

и класс ребенка :

function Lion() { 
    // do something 
} 

, если я хочу Lion наследовать Animal «s прототип обычной практикой это :

Lion.prototype = new Animal(); 

// Set the constructor to Lion, because now it points to Animal 
Lion.prototype.constructor = Lion; 

Разве это ничем не отличается от этого (как результат не как производительность)?

$.extend(Lion.prototype, Animal.prototype); 

Для не разработчиков Jquery: $.extend копирует все методы прототип и атрибуты, по одному из животных в Lion.

Я не большой эксперт по наследованию в javascript. Обычно я использую структуру MVC для разработки интерфейса, где все просто работает, но теперь я хотел бы также понять, как работает наследование прототипа.

ПРИМЕЧАНИЕ! Я прочитал много статей о предмете, я знаю, что существует много "plugins", который реализует функциональность класса. Это не что мне нужно. Пожалуйста, ответьте на вопрос, а не просто ссылку на статьи о предмете (за исключением случаев, когда это отвечает).

Спасибо!

+1

'$ .extend' в JQuery реализует ** Смешение ** шаблон JavaScript, предназначенный в первую очередь клонировать объекты и добавлять новые реквизиты и методы; где изменение прежнего объекта не влияет на новое. Подумайте об этом как о новом 'Object.create' в Harmony, с одним отличием -' newObj = Object.create (oldObj) 'делает' oldObj' '__proto__' статьи' newObj' –

ответ

3

Там разница, копирование свойств между двумя прототипами, не делает их «связаны» друг с другом, а именно:

$.extend(Lion.prototype, Animal.prototype); 

// add one more method to the prototype 
Animal.prototype.test = function() { 
    alert('test'); 
}; 

var x = new Lion(); 
x.test(); // TypeError: Object <Lion> has no method 'test' 

Вы не имели бы это, если вы используете new Animal() в качестве прототипа для Lion , как показано here.

3

Я недавно написал статью, которая объясняет Why Prototypal Inheritance Matters. Это немного долго, но стоит прочитать.

Чтобы ответить на ваш вопрос напрямую, да Lion.prototype = new Animal отличается от $.extend(Lion.prototype, Animal.prototype), потому что:

  1. В первом случае вы используете delegation.
  2. Во втором случае вы используете concatenation.

Сообщение, которое я связал с вами, объясняет истинное прототипное наследование (т. Е. Прототипное наследование с использованием прототипа).

Это как ваша программа будет выглядеть, если вы использовали истинное прототипичное наследование в JavaScript:

var animal = { 
    create: function() { 
     return this.extend(); 
    }, 
    walk: function() { 
     alert("I am walking."); 
    } 
}; 

var lion = animal.extend({ 
    create: function() { 
     return animal.create.call(this); 
    } 
}); 

Здесь функция extend является один из поста я связан вам.

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

Вот скрипка, которая показывает истинное прототипичное наследование в действии: http://jsfiddle.net/6x4BU/

+2

Nice (хотя я не поделитесь всеми своими взглядами). По крайней мере, включение перечислимых свойств в Object.prototype - это плохая практика! И эти массивы 'clones' предотвратят сбор мусора. – Bergi

+0

@ Bergi - Это замечательное наблюдение. Я попытаюсь найти решение этого. Спасибо. –

+0

@ Bergi - Не могли бы вы опубликовать тот же комментарий на моем блоге, чтобы другие могли его прочитать. –

1

Нет, они не являются одинаковыми.

Первый пример прототипа Lion: экземпляр животных. Этот экземпляр наследует от прототипа Animal и связывается с этим прототипом. Если прототип Animal изменен, это повлияет на экземпляр.

Второго пример просто копирования свойств от прототипа животных и Lion не будет связан с фактическими животными самого прототипа.

0

Как уже упоминалось, да есть разница.

В первом примере изменения прототипа Animal изменят поведение экземпляров Lion.

Во втором примере Lion наследует возможности Animal во время вызова $ .extend().

Первый способ имеет некоторые, возможно, вредные побочные эффекты, хотя, в частности:

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

  • Первый метод не допускает избирательное наследование от Animal. Это все или ничего. Вы хотели банан, но у вас были горилла, банан и все джунгли. (Эта известная проблема называется проблемой гориллы/банана). Последний метод позволяет выборочно наследоваться от животных: $.extend(Lion.prototype, { run: Animal.prototype.run, sleep: Animal.prototype.sleep });

  • instanceof разрывов с конкатенацией - но instanceof не является надежной в любом случае. Если вы переназначите прототип Animal, он сломается. Если вы попытаетесь использовать его в контекстах исполнения, он прерывается. Другими словами, не используют instanceof, независимо от того, какой метод наследования вы выберете.

Функции конструктора необязательны. Вы можете просто создать объект буквального под названием животного и сделать это:

lion = Object.create(animal); 

Еще лучше, если положить, что в функции фабрики: Функции

function lion(options) { 
    return $.extend(Object.create(lion), options); 
} 

завода имеют много преимуществ по сравнению с конструктором, который я не буду иди сюда.Вы можете увидеть больше деталей в моем ответе на этот пост: Constructor function vs Factory functions

0

Это базовый прототип наследование в чистом JavaScript

// base class declaration 
function Animal (arg) { 
    this.arg = arg; 
} 

// just a method in the Animal class, it can be whatever you want 
Animal.prototype.roar = function() { 
    alert(this.arg); 
}; 

// object that inherits the base class 
function Lion (arg) { 
    // the call to the super constructor 
    Animal.call(this, arg); 
} 

// the prototypical inheritance 
Lion.prototype = Object.create(Animal.prototype); 
// the constructor needs to be set so that it does not show as the base constructor 
// otherwise the constructor for all instances of Lion will show as Animal 
Lion.prototype.constructor = Lion; 

var symba = new Lion('the lion is roaring'); 

symba.roar(); 
Смежные вопросы