Это смущает многих людей, потому что Javascript использует совершенно другое понятие наследования и класса. В Javascript все , включая классы, является просто объектом. Все методы и такие, которые составляют часть class , содержатся в объекте с именем prototype
. Частично это функция с именем init
. Когда вы делаете new Foo()
, вы создаете новый объект, и некоторый метод init
копирует соответствующее содержимое, включая прототип, в этот новый объект.
Итак, когда вы добавляете функцию к prototype
через
myClass.prototype.example1 = function(){};
вы фактически добавляете в класс 1016 * новый метод, который затем наследуется в любом экземпляре myClass, который вы создаете. Во втором случае
myClass.example2 = function(){};
вы просто добавляете новый метод в исходный объект myClass. В терминах Java это в основном меняет его на объект нового типа, который действует как myClass , за исключением , теперь у него есть метод example2()
.
Обновление
В другом ответе упоминается Классическая записка Крокфорда о наследовании. Я бы порекомендовал прочитать также бумагу Prototypal Inheritance .
Еще одно обновление
Хорошо, давайте вернемся на секунду. Во-первых, что это за объект? По сути, это структура, которая сочетает в себе состояние и поведение .
У нас есть идея Числа, у которого есть метод add, и у нас есть своего рода Число, называемое Целым числом, которое «ведет себя как» Число, но ограничено значениями в определенном диапазоне. На таком языке, как Java, у вас может быть
abstract class Number {
public void addTo(Number arg);
}
, а затем
class Integer extends Number {
int val;
public void addTo(Integer arg){ val += arg; }
}
(И не беспокойте меня о деталях Java, я пытаюсь сделать вывод.)
То, что вы сказали здесь, это то, что потенциально есть много объектов, которые являются числами, и все они имеют поведение, называемое addTo
. Математически набор вещей, которые идентифицируются общим свойством, иногда называют «классом эквивалентности», и именно так мы получаем имя «класс».
Мы также определили особый вид Number, называемый Integer, который имеет ограниченный диапазон значений, от -32767 до 32768. (Тест: почему эти значения?) Тем не менее, он действует во всех отношениях как Number: Вы также можете addTo
целых чисел. Это утверждение «действует во всех отношениях как - но с этими ограничениями» обычно сокращается до «является» и является тем, что мы подразумеваем под «наследованием».
Итак, теперь вы пишете
Integer a, b;
// they get initial values somehow, left as an exercise
a.addTo(b);
и компилятор выясняет, чтобы найти объект a
, находит его конкретное поведение addTo
и знает, как все подключить, чтобы он работал. Иногда - как в ранних версиях C ++ - это нужно было делать во время компиляции; в более поздних версиях C ++ и Java также есть способ установить соединение во время выполнения («позднее связывание»), что в основном сводится к тому, чтобы разместить таблицу где-нибудь с надписью
Если у меня есть целое число и мне нужен метод addTo, вот его адрес; используйте это.
Javascript и некоторые предыдущие языки, начиная с Self, делают это немного по-другому. Теперь объект - это просто структура, которая содержит ... материал. Некоторые из этих вещей могут быть данными, а некоторые могут быть функциями. Идея «класса» может быть полностью абстрагирована; «класс» - это просто набор всех объектов, имеющих одинаковое содержимое. Итак, в Javascript мы могли бы сделать наш класс "Integer" как
var Integer = { // we're defining an object as a literal
int val,
addTo : function(b){ val += b ; }
}
(Опять же, не беспокойтесь, если это действительно идеальный javascript, смысл в том, чтобы объяснить концепцию.)
Если мы скопируем этот объект с именем Integer
, скажем, Integer2
, тогда оба будут содержать val
и функцию с именем addTo
. Мы можем сказать, что они оба «одного и того же класса», потому что они имеют одинаковое состояние и методы.
Вопрос в том, как мы можем реализовать это копирование?Вы можете просто пройтись по всему понемногу, но у него есть некоторые другие проблемы, поэтому мы определили специальный объект в содержимом каждого объекта javascript с именем prototype
и поместили все методы ивещи - все, что мы хотели бы скопировать для создания другого объекта в том же классе - в этом.Теперь у нас будет что-то вроде
var Integer = {
prototype : {
int val,
addTo : function(b){ val += b; }
}
}
Мы добавим к языку оператор new
, который просто копирует объект-прототип.Когда мы пишем
var a = new Integer();
a
, это теперь объект, который имеет тот же прототип, что и все другие Integer
объекты.Когда мы пишем
a.addTo(b);
, все, что нужно сделать интерпретатору, - это посмотреть на объект prototype
, содержащийся в a
, и найти его метод с именем addTo
.
Зачем это?Потому что теперь вся сложность компиляции в классах, добавления синтаксиса и выяснения того, когда связывать во время компиляции или во время выполнения, плюс управление таблицами времени выполнения и т. Д., Превращается в две простые операции:
- знать, как сделать глубокую копию из
prototype
- как найти что-то по имени в
prototype
.
Этот второй подходэто «наследование прототипа».