#javascript #constructor #prototype #prototype-chain
#javascript #конструктор #прототип #прототип-цепочка
Вопрос:
Я имею в виду этот веб-архив статьи, первоначально посвященной Helephant.com , чтобы узнать, как Javascript разрешает функции в цепочке прототипов при вызове объектов.
В статье приводятся цитаты,
Если у объекта нет метода, установленного непосредственно для него, javascript затем ищет функцию-конструктор, которая создала объект. Javascript проверяет свойство prototype конструктора для метода.
В следующем коде, если вы проверяете rufus.constructor
глобальный Object()
конструктор, JS будет напрямую проверять глобальный объект (), поскольку rufus.constructor
Object()
или согласно цитате из статьи выше, сначала он посмотрит на конструктор, а затем найдет свойство prototype и так далее.. Как JS разрешит функцию ( rufus.toString
) . Я совершенно сбит с толку этим.
//PET CONSTRUCTOR
function Pet(name, species, hello)
{ this.name = name;
this.species = species;
this.hello = hello; }
Pet.prototype = {
sayHello : function(){
alert(this.hello);
}
}
//CAT CONSTRUCTOR
function Cat(name, hello, breed, whiskerLength)
{ this.name = name;
this.hello = hello;
this.breed = breed;
this.whiskerLength = whiskerLength;}
Cat.prototype = new Pet();
var rufus = new Cat("rufus", "miaow", "Maine Coon", 7);
rufus.toString;
Комментарии:
1. есть ли еще что-нибудь неясное?
Ответ №1:
Если у объекта нет метода, установленного непосредственно для него, javascript затем ищет функцию-конструктор, которая создала объект. Javascript проверяет свойство prototype конструктора для метода.
Формулировка сбивает с толку. JavaScript просматривает цепочку прототипов __proto__
и не использует constructor
свойство. Они упомянули Constructor
, потому что обычно именно так объекты получают свое свойство prototype — through Constructor.prototype
. Но это не всегда так. Вы можете установить прототип следующим образом:
var rufus2 = Object.create(new Pet());
Object.getPrototypeOf(rufus) === Object.getPrototypeOf(rufus2); // true
Относительно того, как toString
решается метод:
rufus.hasOwnProperty('toString'); // false -> go up
(new Pet()) rufus.__proto__.hasOwnProperty('toString'); // false -> go up
({sayHello :...}) rufus.__proto__.__proto__.hasOwnProperty('toString'); // false -> go up
(Object.prototype) rufus.__proto__.__proto__.__proto__.hasOwnProperty('toString'); // true
Комментарии:
1. @Maximums, вы уверены, что JS фактически никогда не использует
constructor
свойство для поиска свойств / методов. Я хотел бы верить, что для этого не должно требоваться искать свойство конструктора, когда каждый объект имеет прямой указатель / путь (через proto ) к своему классу наследования, однако автор, ИМХО, достаточно осведомлен, судя по прочтению всех ее статей.2. @Maximums, далее в этой статье говорится, что > В браузерах на базе Mozilla каждый объект предоставляет другое свойство, называемое proto , которое дает вам доступ к способу отслеживания браузером цепочки прототипов.
3. Означает ли это, что этот пост иллюстрирует 2 разных способа, используемых браузерами для разрешения свойств и методов. Браузеры на базе Mozilla через ( proto ) и другие браузеры (на основе IE и webkit), как она описала через
constructor
поиск свойств.4. Далее на [
__proto__
странице] Mozilla ( developer.mozilla.org/en-US/docs/Web/JavaScript/Reference / … ) утверждает >> Только недавно свойство proto было стандартизировано в спецификации языка ECMAScript 6 для веб-браузеров>> значит ли это, что то, что она написала о поиске свойств / методов с использованием маршрута свойств ‘constructor’, она конкретно ссылается на более старыебраузеры без браузеров на базе Mozilla, т.Е. Все старые браузеры на базе IE и webkit.5. обратите внимание, статья была очень старой, написанной на
17 Aug 09
.
Ответ №2:
function Person () { }
Person.prototype.sayName = function () { };
var bob = new Person();
console.log(bob.sayName === Person.prototype.sayName); // true
console.log(bob.constructor.prototype.sayName === Person.prototype.sayName); // true
console.log(bob.__proto__.sayName === Person.prototype.sayName); // true
console.log(bob.constructor === Person); // true
console.log(bob.__proto__ === Person.prototype); // true
Это ваши отношения.
Если свойство / функция не может быть найдена для объекта, он поднимается по __proto__
цепочке, чтобы найти то, что он ищет. В старых браузерах __proto__
он был недоступен для разработчиков JS, но по-прежнему оставался объектом, который браузер / узел использовал за кулисами, чтобы ссылаться на свойство Constructor.prototype .
PS: старайтесь не использовать глубокую иерархию в JS. Это путь многих разрывов. Глубокие иерархии вызывают боль в других языках, основанных на классах, но являются проблемой в JS, где часто достаточно функции.
Комментарии:
1. Можете ли вы, пожалуйста, попытаться ответить в контексте кода, который я опубликовал, object (
rufus
) наследуется от object (Cat.prototype = new Pet()
) другого типа (Pet
), чей прототипPet.prototype
сам наследуется от globalObject.prototype
({}
) . В вашем коде объекты constructor и prototype довольно очевидны и мало помогают понять, где наследование в гораздо более сложных структурах наследования, как в моем случае.