Вопрос или проблема
предположим, что это мой фрагмент кода
let myHeroes = ["тор", "человек-паук"];
let heroPower = {
тор: "молот",
человек-паук: "паутина",
getSpiderPower: function () {
console.log(`сила паука равна ${this.человек-паук}`);
}
};
heroPower.getSpiderPower();
heroPower.__proto__.getThorPower = function () {
return `сила тора равна ${heroPower.тор}`;
};
heroPower.getThorPower();
Теперь, поскольку обычные объекты в JavaScript не имеют доступа к прототипу, чтобы добавить эту функциональность к объекту heroPower, мне действительно нужно писать __proto__
после имени объекта, чтобы добавить свойства, или есть другой простой способ?
Я пытался использовать heroPower.prototype.getThorPower=function(){..}
, но это вызвало ошибку. Я ожидаю добавить функцию getThorPower внутри объекта heroPower, не определяя эту функцию явно внутри объекта, вставляя ее снаружи объекта.
Ответ или решение
Почему обычные объекты в JavaScript не имеют доступа к свойству prototype и необходимость использовать proto
Согласно спецификации JavaScript, объекты являются основой объектно-ориентированного программирования в этом языке. Однако между обычными объектами, созданными с помощью литералов или конструктора объекта, и функциями существует фундаментальное различие. В частности, обычные объекты не имеют свойства prototype
и несколько отличаются в своих возможностях в отношении наследования и расширения функциональности.
Обычные объекты и свойство prototype
-
Отсутствие prototype у объектов:
Обычные объекты в JavaScript, такие как ваш объектheroPower
, имеют внутреннее свойство, называемое[[Prototype]]
, но не имеют доступа к свойствуprototype
. Это свойство доступно только для функций, создаваемых с помощью конструктора. В результате, поэтому у обычных объектов нет возможности напрямую добавлять методы вprototype
, и они не могут быть унаследованы другими объектами. -
Использование proto для доступа к прототипу:
Чтобы добавить методы или свойства в прототип обычного объекта, вам необходимо обращаться к его встроенному прототипу через__proto__
. В вашем примере:heroPower.__proto__.getThorPower = function () { return `thor power is ${heroPower.thor}`; };
Данная конструкция работает, так как
heroPower.__proto__
указывает на объект-прототип, который расширяется для включения нового методаgetThorPower
.
Как использовать prototype правильно
Проблема использования prototype
с обычными объектами заключается в том, что:
-
Конструкторы: Для создания объекта с доступом к
prototype
, следует использовать функцию-конструктор. Например:function HeroPower() { this.thor = "hammer"; this.spiderman = "sling"; } HeroPower.prototype.getThorPower = function() { return `thor power is ${this.thor}`; }; let heroPower = new HeroPower(); console.log(heroPower.getThorPower());
-
Классическая и современная парадигма: В современном JavaScript (с ES6 и выше) вы также можете использовать синтаксис классов, который автоматически создает
prototype
для экземпляров:class HeroPower { constructor() { this.thor = "hammer"; this.spiderman = "sling"; } getThorPower() { return `thor power is ${this.thor}`; } } let heroPower = new HeroPower(); console.log(heroPower.getThorPower());
Заключение
Таким образом, использование __proto__
является единственным способом добавления методов к прототипу обычного объекта, поскольку сами объекты не имеют свойства prototype
. Однако помимо этого существует альтернатива: использование функций-конструкторов или классов, которые предоставляют возможность создания объектов с наследуемыми свойствами и методами. Это не только более чистый и поддерживаемый подход, но и спецификация JavaScript способствует созданию иерархии, что позволяет создавать более сложные структуры и аин исчерпывающе вести работу с объектами.