Что это значит, что Javascript - это язык, основанный на прототипах?

255

Говорят, что одним из основных преимуществ Javascript является то, что это язык на основе прототипов.

Но что это означает, что Javascript основан на прототипах, и почему это преимущество?

Йонас Пегерфальк
источник
3
Этот ответ объясняет все, что вам нужно знать о наследовании прототипов: stackoverflow.com/a/16872315/783743
Аадит М Шах,

Ответы:

291

Прототипное наследование является формой повторного использования объектно-ориентированного кода . Javascript - один из единственных [основных] объектно-ориентированных языков, использующих наследование прототипов. Почти все другие объектно-ориентированные языки являются классическими.

В классическом наследовании программист пишет класс, который определяет объект. Несколько объектов могут быть созданы из одного и того же класса, поэтому у вас есть код в одном месте, который описывает несколько объектов в вашей программе. Классы могут быть организованы в иерархию, что способствует повторному использованию кода. Более общий код хранится в классе более высокого уровня, от которого наследуются классы более низкого уровня. Это означает, что объект совместно использует код с другими объектами того же класса, а также со своими родительскими классами.

В прототипной форме наследования объекты наследуются непосредственно от других объектов. Все дела о занятиях уходят. Если вам нужен объект, вы просто пишете объект. Но повторное использование кода по-прежнему ценно, поэтому объектам разрешено связывать их вместе в иерархии. В javascript каждый объект имеет секретную ссылку на объект, который его создал, образуя цепочку. Когда у объекта запрашивается свойство, которого у него нет, его родительский объект будет запрашиваться ... непрерывно вверх по цепочке, пока свойство не будет найдено или пока не будет достигнут корневой объект.

Каждая функция в JavaScript (которые сами являются объектами) на самом деле имеет член с именем «prototype», который отвечает за предоставление значений при запросе у них объекта. Наличие этого члена позволяет механизму конструктора (с помощью которого объекты создаются из функций) работать. Добавление свойства к прототипу объекта функции сделает его доступным для созданного объекта, а также для всех объектов, которые наследуются от него.

преимущества

Не может быть жесткого и быстрого правила относительно того, почему наследование прототипов является выгодной формой повторного использования кода. Повторное использование кода выгодно, и наследование прототипов - разумный способ добиться этого. Вы можете возразить, что наследование прототипов - довольно простая модель повторного использования кода, и этот код может быть многократно использован прямым способом . Но классические языки, безусловно, способны достичь этого.

Замечание: @ Эндрю Хеджес отмечает, что на самом деле существует множество прототипных языков. Стоит отметить, что эти другие существуют, но также стоит отметить, что ни один из них не имеет ничего общего с мейнстримом. NewtonScript, казалось, какое-то время набирал обороты, но умер с его платформой. Также возможно расширить некоторые современные языки способами, которые добавляют возможности прототипа.

keparo
источник
9
Привет, Келли. Хотя JavaScript , безусловно, является самым популярным языком прототипов, существует множество других: en.wikipedia.org/wiki/Prototype-based_programming#Languages
Эндрю Хеджес,
2
Привет, Андрей. Хорошая точка зрения. Я должен был быть более ясным. Я запомню это.
Кепаро
3
Пожалуйста, прочтите это также developer.mozilla.org/en/JavaScript/Guide/…
pramodc84
1
+1 за отличный ответ. Небольшое замечание: для меня классическое наследование кажется более «прямым», чем прототип. На самом деле, я действительно рассматриваю объект-прототип как простую связь (с другими объектами), тогда как в скомпилированном ООП я считаю базовый класс «непосредственно унаследованным». Таким образом, объекты-прототипы скорее связаны, чем наследуются (наследование несколько подделано). Есть предположения?
Заключенный НОЛЬ
3
@PrisonerZERO: Я бы сказал, что наследование прототипов более прямое, чем классическое. Вместо объекта B, указывающего на класс, который наследует от класса, на который указывает объект A, он указывает прямо на объект A и говорит: «Я такой же объект, кроме ...». Главное в наследовании прототипов и то, что большинству людей труднее усвоить, заключается в том, что оно не различает экземпляры от типов. Каждый объект является как типом, так и экземпляром. Различия между ними являются искусственными и преднамеренными и обычно являются симптомом застревания в мышлении, ориентированном на класс.
Чао
54

Язык на основе прототипов не делает различий между классами и объектами: он просто имеет объекты. Основанный на прототипе язык имеет понятие прототипного объекта, объекта, используемого в качестве шаблона для получения начальных свойств для нового объекта. Любой объект может указывать свои собственные свойства, либо при его создании, либо во время выполнения. Кроме того, любой объект может быть связан как прототип для другого объекта , что позволяет второму объекту совместно использовать свойства первого объекта.

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

Программирование на основе прототипов - это стиль объектно-ориентированного программирования, в котором отсутствуют классы, а повторное использование поведения (или наследование в языках на основе классов) выполняется путем клонирования существующих объектов, которые служат прототипами.

CMS
источник
Вы все еще чувствуете это? Потому что если это так, то это первое объяснение, которое когда-либо действительно просто «щелкнуло» мной.
Chazt3n
11

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

Выше возможно, потому что объекты по сути являются функциями в сценарии Java (также замыкания).

questzen
источник
Динамические объекты являются преимуществом javascript, но на самом деле они не связаны с тем, чтобы javascript был прототипом или функциональным языком. Во многих классических языках вы можете создавать динамические объекты во время выполнения. Закрытия также несколько не связаны.
keparo
2
Классы не обязательно являются статическим кодом - взгляните на Python, в котором классы сами являются объектами и построены из метаклассов, которые также являются объектами.
Томаш Зелиньски
6

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

Greg
источник
6

Если вы просто используете объекты во время выполнения вместо класса при компиляции для создания новых объектов, это открывает возможность расширения объекта без знания каких-либо подробностей о нем. Конечно, это может стать недостатком довольно быстро в зависимости от использования. Я не делаю никаких предположений о языке здесь, поэтому он применим к языкам, отличным от javascript, которые не так динамичны.

myobject.prototype=unkownobject;
myobject.newproperty=1;

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

Обратите внимание, что язык не должен реализовывать наследование прототипов, таких как javascript. В javascript объект-прототип является просто общим, так же как и его свойства среди наследников. Альтернативой является копирование всех свойств прототипа в новый объект. Каждый подход имеет свои сильные стороны в разных ситуациях. Мне больше нравится второй, но это не то, что делает javascript.

artificialidiot
источник
6

После прочтения всех ответов это вывод

1) Наследование, при котором объекты наследуются напрямую от других объектов

2) Это не использует классы

3) Также называется программированием на основе экземпляров или бесклассовым программированием, ориентированным на прототипы.

4) Повторное использование поведения выполняется путем клонирования существующих объектов, которые служат прототипами

5) Объект, используемый в качестве шаблона из нового объекта, получает начальные свойства

Сунил Гарг
источник