Чтобы понять прототип в JS, вы должны сначала понять следующие концепции
1. Все в JS - это объект
2. Все в JS получено из объекта, то есть конечная точка цепочки прототипа всех вещей указывает на объект.
// [«Конструктор», «Тостронг», «Толокалинг», «ValueOf», «HasownProperty», «Isprototypeof», // «ProperateSeNumerable», «__definegetter__», «__lookupgetter__», «__definesetter__»,// __lookseteter__ "," __definesetter__ ",//" "__looksetter__", "__definesetter__",// "", "__looksetter__", "__definestter__",/ "", "__lookupgetter__", "__definegetter__", "__lookupgetter__", "__definegetter__", "__lookupgetter__", "__definegetter__" console.log (object.getownpropertynames (object.prototype));
3. Тонкая связь между конструкторами и экземплярами (объектами) в JS
Конструкторы определяют прототипы, чтобы договориться о спецификациях их экземпляров, а затем строят экземпляры через новые. Их функция заключается в создании объектов.
Сам конструктор (метод) является экземпляром метода (функции), поэтому его также можно найти для его __proto __ (протохаин)
Object / function f () {} Это конструктор, один предоставляется нативным API JS, а другой настроен
New Object () / new F () - экземпляр
Примеры можно просмотреть только «только», чтобы выяснить, на каком прототипе он сделан.
Прототип, который «не может» переопределить экземпляр, а затем обманывает себя, чтобы создать экземпляр экземпляра.
Практика для создания истинного знания, и только наблюдая/думая о себе, вы можете по -настоящему понять:
// Давайте сначала посмотрим, что конструктор // function empty () {} function empty () {} console.log (function.prototype, function .__ Proto__); // Object {} function empty () {} console.log (object.prototype, object .__ Proto__); function f () {} // f {} function empty () {} console.log (f.prototype, f .__ Proto__);Вы можете голодать, давайте разберем это.
прототип
Формат вывода прототипа: прототип названия конструктора
Во -первых, давайте посмотрим, какой объект.
Object {} -> Предыдущий объект -это имя конструктора, а следующий представляет прототип. Вот {}, то есть экземпляр объекта объекта (пустой объект)
Тогда f {} мы понимаем, что это значит. F - это имя конструктора, а прототип также является пустым объектом
// давайте посмотрим на пример, построенный конструктором var o = new Object (); // var O = {}; // неопределенный объект {} console.log (o.prototype, o .__ Proto__); функция f () {} var i = new f (); // неопределенная f {} console.log (i.prototype, i .__ Proto__);Давайте пойдем немного глубже и определим прототип F, чтобы увидеть, что произойдет?
function f () {} f.prototype.a = function () {}; var i = new f (); // неопределенная f {a: function} console.log (i.prototype, i .__ Proto__);Таким образом, мы можем ясно видеть, что я построен из F, прототип - {a: function}, что означает, что метод A был добавлен к исходному прототипу пустого объекта.
Давайте изменим ситуацию, что произойдет, если прототип, который полностью покрывает F?
function f () {} f.prototype = {a: function () {}}; var i = new f (); // неопределенный объект {a: function} console.log (i.prototype, i .__ Proto__);Эй ~ Почему это указывает на то, что я построен из объекта? Нет!
Поскольку мы полностью перезаписываем прототип F, на самом деле мы указываем прототип как объект {a: function}, но это приведет к потере исходной информации конструктора и станет конструктором, указанным объектом {a: function}.
Итак, что такое конструктор объекта {a: функция}?
Потому что объект {a: функция} на самом деле относится к
var O = {a: function () {}} // новый объектТогда конструктор O, конечно, является объектом
Давайте поправляем эту ошибку
function f () {} f.prototype = {a: function () {}} // повторно определять правильный конструктор f.prototype.constructor = f; var i = new f (); // неопределенная f {a: function, конструктор: функция} console.log (i.prototype, i .__ Proto__);Теперь вы можете снова получить правильную информацию о прототипе ~
Прототип цепочка
Тогда давайте посмотрим, что такое прототипная цепочка?
Проще говоря, это то же самое, что отношения наследования (цепь) в ООП. Посмотрите слой за слоем до конечного объекта.
Самое главное, чтобы выяснить, что в JS (экземпляры) объекты. Это просто, все в JS - это объекты!
Тогда нам нужно выяснить, что у любого объекта есть прототип!
Тогда давайте докажем:
Объект // Это функция, функция является объектом функции экземпляра, так что это объект .__ Proto__ == function.prototype // Затем прототип объекта, true // Это обычный объект, поэтому экземпляр объекта принадлежит функции. Object.Prototype .__ Proto__ == null // true function // Это также функция, да! Функция .__ Proto__ == function.prototype // true function a () {} // Это пользовательская функция, и в конце концов, это все еще функция, это верно! A .__ Proto__ == function.prototype // Любая функция является экземпляром функции, так же прототип A? var a = new a () a .__ Proto__ == A.prototype // экземпляр A построен конструктором A, поэтому прототип A определяется атрибутом прототипа A.prototype .__ Proto__ == Object.prototype // Пример обычных объектов - объекты.Прототип и __proto__
Каждый объект содержит __proto__, указывающий на «прототип» объекта.
Похоже, каждая функция содержит прототип. Для чего это объект прототипа?
Давайте посмотрим на следующий код, используя конструктор для создания объекта (приведенное выше предназначено создание объекта в форме буквальной формы).
function foo () {}; var foo = new foo (); console.log (foo .__ Proto__);Представьте себе, что будет указывать __proto__ этого объекта Foo?
Объект, содержащий атрибут конструктора? Неважно, если вы этого не понимаете. Распечатайте атрибут прототипа функции Foo и сравните его с вами, чтобы узнать.
function foo () {}; var foo = new foo (); console.log (foo .__ proto __); console.log (foo.prototype); console.log (foo .__ Proto__ === foo.prototype);Оказывается, что __proto__ объекта, который выходит из нового, указывает на прототип функции Foo.
foo .__ Proto__ -> foo.prototype
Какой смысл проектирования JS, как это? Вспоминая то, что было упомянуто выше, в мире JS объекты не создаются на основе классов (плесени), но получены из прототипов (другой объект).
Когда мы выполняем новые операции для создания нового объекта, мы не будем глубоко вдаваться в конкретную реализацию новых операций, но мы уверены в одном - то есть мы указываем на объект прототипа для нового объекта __proto__.
Только этот код
function foo () {}; var foo = new foo ();На кого указывают Foo .__ Proto__? Почему вы не можете указать на функцию самого Foo? Хотя функция также является объектом, я подробно расскажу об этом, если у вас есть шанс. Но, конечно, не подходит указывать на Foo .__ Proto__foo, потому что Foo является функцией с большим количеством логического кода. Как объект, он не имеет значения наследовать логическую обработку. То, что он хочет наследовать, - это атрибут «объекта прототипа».
Следовательно, каждая функция будет автоматически генерировать объект прототипа, а __proto__ объекта нового из этой функции указывает на прототип этой функции.
foo .__ Proto__ -> foo.prototype
Суммировать
Сказав так много, я до сих пор не объяснил это полностью, поэтому лучше быть на предыдущей картине. Я ссылался на фотографии из других пользователей сети, но я всегда чувствую, что я не объясняю ясно, поэтому я сам нарисовал картину. Если я думаю, что у меня все хорошо, пожалуйста, нравится! (Я старался изо всех сил, чтобы нарисовать).
Давайте сделаем этот снимок и запомним следующие факты:
1. В каждом объекте есть атрибут _proto_.
В мире JS нет концепции класса (плесени). Объекты получены из другого объекта (прото), поэтому в каждом объекте будет появляться атрибут _proto_, указывающий на его объект прототипа. (См. Объект OBJ, определенный в буквальной форме в верхнем левом углу. Он открывает пространство для хранения собственных свойств объекта в памяти, и генерирует _proto_, указывающий на свой прототип - объект прототипа верхнего уровня.)
2. Каждая функция имеет свойство прототипа.
Почему «конструктор» называется конструктором? Потому что он хочет построить объект. Таким образом, согласно первому факту, выше, кто делает атрибут _proto_ построенного нового объекта? Вы не можете указать на сам конструктор. Хотя это также объект, вы не хотите, чтобы новый объект наследовал свойства и методы функции. Следовательно, каждый конструктор будет иметь атрибут прототипа, указывающий на объект как прототип нового объекта, построенного этим конструктором.
3. Функции также являются объектами.
Каждая функция обладает некоторыми общими свойствами и методами, такими как Apply ()/call () и т. Д., Но как эти общие методы унаследованы? Как создаются функции? Представьте себе, что все является объектом, включая функции, и является объектом, построенным через конструктор. Затем, согласно второму факту выше, каждая функция также будет иметь прототип, указывающий на его конструктор. Функцией этого конструктора является функция, и все функции в JS построены из функции. Общие свойства и методы функций хранятся на функции объекта прототипа. Прототип.