Выглядит немного странно для меня.
Вот как работает настройка прототипов, назначенных функциями конструктора. И вы не единственный, кто считает это неудобным, см. Ниже. :-) (Update:. И смотри ниже для того, как ES6 делает это намного проще)
Это работает, если добавить функцию внутри класса (удаление .protoype и т.д.), но я являюсь сказал, чтобы определить функцию outisde объекта.
Если вы сделаете это:
function Man(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
this.getName = function() {
return this.firstName + this.lastName;
};
}
... то каждый Man
объекта получает свою собственную копии функции. Они не разделяют, вы получаете новый функциональный объект для каждого объекта Man
. (Умный движок может повторно использовать базовую функцию код, но там будет - это два функциональных объекта.) Целью прототипов является создание функций, которые могут совместно использоваться объектами, построенными конструктором.
Другое замечательное в прототипах заключается в том, что соединение объекта с прототипом продолжается, что означает, что вы можете добавлять функции к уже существующим объектам, добавляя их к прототипу. Пример:
как мы добавили
introduction
к прототипу
после
joe
был создан
function Man(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
Man.prototype.getName = function() {
return this.firstName + " " + this.lastName;
};
var joe = new Man("Joe", "Bloggs");
console.log(joe.getName()); // "Joe Bloggs"
Man.prototype.introduction = function() {
return "Hi there, I'm " + this.getName();
};
console.log(joe.introduction()); // "Hi there, I'm Joe Bloggs"
Примечание. Это не имеет значения, поиск динамичен. Когда вы делаете joe.introduction
, двигатель ищет объект introduction
на joe
и, если он не находит его, он смотрит на прототип. Таким образом, добавление в прототип позже (косвенно) улучшает существующие объекты.
Вы не единственный, кто считает синтаксис неудобным. Вы часто видите, что люди создают «extend
» методы, подобные тем, которые используются в jQuery, подчёркивании, прототипе и т. Д. Метод extend просто присваивает свойства исходного объекта целевому объекту.Простая форма этого является:
function extend(target, source) {
var name;
for (name in source) {
target[name] = source[name];
}
}
... хотя, как правило, вы видите что-то с более широкими возможностями (несколько объектов-источников, возвращение назначения и т.д.).
И тогда вы можете использовать его как это:
function Man(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
extend(Man.prototype, {
getName: function() {
return this.firstName + this.lastName;
},
introduction: function() {
return "Hi there, I'm " + this.getName();
}
});
Это использует синтаксис инициализатора объекта (иногда называемый «литерал объекта»), передает его в extend
и extend
помещает свойства на Man.prototype
.
Вы также видите такие вещи, как my Lineage
script, которые упрощают этот синтаксис и обрабатывают несколько других вещей (например, вызов функции-прототипа функции-источника).
По ES6, которая очень близка к завершению, и делает свой путь в браузеры (вы также можете transpile), это становится намного проще:
class Man {
constructor(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
getName() {
return this.firstName + " " + this.lastName;
}
introduction() {
return "Hi there, I'm " + this.getName();
}
}
var joe = new Man("Joe", "Bloggs");
console.log(joe.getName()); // "Joe Bloggs"
console.log(joe.introduction()); // "Hi there, I'm Joe Bloggs"
Это просто, как работает Javascript. Это не классический язык OO. Почему большое дело? – MaxArt
Почему бы вам не динамически создавать каждый метод только при инициализации экземпляра класса? – Blender
@Blender: поскольку точка прототипического наследования не делает этого :-) – Bergi