Позвольте мне дать более полный ответ, который я узнал во время учебного курса JavaScript.
В большинстве ответов упоминалась разница уже, т. е. когда прототипирование функции делится со всеми (будущими) экземплярами. В то время как объявление функции в классе создаст копию для каждого экземпляра.
В общем, нет правильного или неправильного, это больше зависит от вкуса или дизайнерского решения в зависимости от ваших требований. Прототипом, однако, является метод, который используется для разработки в объектно-ориентированном виде, как я надеюсь, вы увидите в конце этого ответа.
Вы показали два шаблона в своем вопросе. Я попытаюсь объяснить еще два и попытаться объяснить различия, если это уместно. Не стесняйтесь редактировать / продлевать. Во всех примерах речь идет о объекте автомобиля, который имеет местоположение и может перемещаться.
Не уверен, что этот шаблон по-прежнему актуальен в настоящее время, но он существует. И это хорошо знать об этом. Вы просто передаете объект и свойство функции декоратора. Декоратор возвращает объект с помощью свойства и метода.
var carlike = function(obj, loc) {
obj.loc = loc;
obj.move = function() {
obj.loc++;
};
return obj;
};
var amy = carlike({}, 1);
amy.move();
var ben = carlike({}, 9);
ben.move();
Функция в JavaScript является специализированным объектом. В дополнение к вызову функция может хранить свойства, подобные любому другому объекту.
В этом случае Car
- это функция (также мыслящий объект), которая может быть вызвана, как вы привыкли делать. Он имеет свойство methods
(которое является объектом с функцией move
). Когда вызывается Car
, вызывается функция extend
, которая делает некоторую магию, и расширяет функцию Car
(мыслящий объект) с помощью методов, определенных в methods
.
В этом примере, хотя
Первые два шаблона позволяют обсуждать использование методов для определения общих методов или использования методов, которые являются определяемый inline в теле конструктора. В обоих случаях каждый экземпляр имеет свою собственную функцию move
.
Прототипная схема не подходит для одного и того же экзамена, поскольку совместное использование функций с помощью делегирования прототипов является самой главной целью прототипа. Как указывали другие, ожидается, что у него будет больше памяти.
Однако есть одна интересная вещь: каждый объект prototype
имеет свойство удобства constructor
, которое указывает на (думаю, объект), к которому он присоединился.
Относительно последних трех строк:
В этом примере Car
ссылки на объект prototype
, который соединяется через constructor
к самому Car
, т. е. Car.prototype.constructor
является Car
. Это позволяет вам выяснить, какая функция конструктора построила определенный объект.
amy.constructor
's поиск завершен и, следовательно, делегирован Car.prototype
, который имеет свойство конструктора. И поэтому amy.constructor
есть Car
.
Кроме того, amy
является instanceof
Car
. Оператор instanceof
работает, видя, что объект прототипа правого операнда (Car
) можно найти где угодно в цепочке прототипов левого операнда (amy
).
var Car = function(loc) {
var obj = Object.create(Car.prototype);
obj.loc = loc;
return obj;
};
Car.prototype.move = function() {
this.loc++;
};
var amy = Car(1);
amy.move();
var ben = Car(9);
ben.move();
console.log(Car.prototype.constructor);
console.log(amy.constructor);
console.log(amy instanceof Car);
Некоторые разработчики могут быть смущены в начале. Пример ниже:
var Dog = function() {
return {legs: 4, bark: alert};
};
var fido = Dog();
console.log(fido instanceof Dog);
Оператор instanceof
возвращает false
, поскольку прототип Dog
не может быть найден нигде в цепочке прототипов fido
. fido
- простой объект, созданный с помощью литерала объекта, т. е. он просто делегирует Object.prototype
.
Это действительно просто еще одна форма прототипа в упрощенной форме и более знакомы для тех, кто программирует на Java, например, поскольку он использует конструктор new
.
Он делает то же самое, что и в прототипном шаблоне, это просто синтаксический саун-надвод прототип.
. Однако основное отличие заключается в том, что в механизмах JavaScript реализованы оптимизации, которые применяются только при использовании псевдоклассического шаблона. Подумайте о псевдоклассическом шаблоне, вероятно, более быстрой версии прототипа; объектные отношения в обоих примерах одинаковы.
var Car = function(loc) {
this.loc = loc;
};
Car.prototype.move = function() {
this.loc++;
};
var amy = new Car(1);
amy.move();
var ben = new Car(9);
ben.move();
Наконец, не должно быть слишком сложно понять, как может быть реализовано объектно-ориентированное программирование. Есть два раздела.
Один раздел, который определяет общие свойства / методы в прототипе (цепочке).
И еще один раздел, где вы помещаете определения, отличающие объекты друг от друга (переменная loc
в примеры).
Это то, что позволяет применять такие понятия, как суперкласс или подкласс в JavaScript.
Не стесняйтесь добавлять или редактировать. Еще раз, я мог бы сделать это сообщество wiki возможно.
существует также другой способ сделать его цикличным выполнением через объекты в d., это не имеет того же assuption, что они будут сохранены в c.__dict__
, который не всегда верен.
d = {'bar': 456}
for key,value in d.items():
setattr(c,key,value)
или Вы могли записать update
метод как часть MyClass
так, чтобы c.update(d)
работы как Вы ожидали это к.
def update(self,newdata):
for key,value in newdata.items():
setattr(self,key,value)
проверяют справку для setattr
setattr(...) setattr(object, name, value) Set a named attribute on an object; setattr(x, 'y', v) is equivalent to ''x.y = v''.
Кроме того, возможно, это был бы хороший стиль, чтобы иметь обертку вокруг метода обновления dict:
def update(self, b):
self.__dict__.update(b)
пз: Извините за не комментарий в сообщение S.Lott, но у меня еще нет представителя.