__proto__ и prototype в JavaScript
Зачем нужен prototype в JavaScript?
При создании любого объекта в JavaScript создается новый объект __proto__ в системе который ссылается на функцию(класс) с помощью которого этот объект создан. При объявлении функции или класса создается также объект с именем prototype. Он создается для того чтобы потомки функции-классы могли унаследовать его свойства или для того чтобы сделать чисто инициализацию конструктора, которая происходит после new когда объявляется любая функция или класс? |
|
Цитата:
Смотрел видео Димыча который ведет уроки в Беларусии по JavaScript, он говорит что при создании функции или класса создается объект prototype, а при создании объекта создается ссылка на этот prototype. А этот человек на маил.ру ответил что ничего не создается. Этот один вопрос. И второй... Цель создания свойства prototype для функции? Чтобы инициализировать конструктортой функции которой я придумал после того как я создам объект своего же класса(функции)? |
|
Цитата:
|
Да, про функцию там нет. В след. статье есть
https://learn.javascript.ru/function-prototype |
>> А этот человек на маил.ру ответил ...
Это был я ![]() >> который ведет уроки по JavaScript ... На мой скромный взгляд пару часов воды разбавленных вкраплениями чуши и бреда. Главное в изучении JavaScript научится пользоваться отладчиком что бы проверять и закреплять полученные знания на опыте. выполни в консоли браузера ff = function fun (){}; f = new ff(); console.dir(f); И изучи из чего состоит полученный объект. Ну и как пример хорошего материала с ютуба правда устарело на кучу лет https://www.youtube.com/watch?v=a3X9uqCoxKY |
Цитата:
1. функции fun 2. конструктора fun 3. __proto__ ссылается на функцию-класс с помощью которого он был создан, то есть на функцию fun. 4. Сама функция fun ссылается на Object.prototype Конструктор как выглядит здесь? Он создается для потомков? |
Цитата:
Объект f не состоит из функции fun. То, что в отладчике написано fun при выводе объекта означает, что это объект "типа fun", т.е порожден с помощью new fun. f - пустой объект. У него нет свойств, кроме __proto__. __proto__ ссылается на объект который содержит свойства constructor и __proto__. Это тот же самый объект на который ссылается fun.prototype. constructor - это ссылка на саму функцию fun Цитата:
|
Тут же нет ничего сложного
Любой объект содержит свойство __proto__, значением которого является ссылка на другой объект, который называется прототипом или null. Любая функция - это тоже объект, который может содержать различные свойства. При создании (определении) функции у нее обязательно создается свойство prototype, значением которого является объект, содержащий свойство constructor, которое является ссылкой на саму функцию. Этот prototype мы потом можем дополнять (или вообще изменить). Итак. Когда мы написали function fun () {} создался fun.prototype = { constructor : fun } Теперь мы можем, например, что то добавлять в fun.prototype fun.prototype.f1 = function () {...}; fun.prototype.f2 = function () {...}; Когда мы создаем новый объект с помощью new let o = new fun() происходит следующее: Создается пустой объект в его свойство __proto__ записывается fun.prototype let o={}; o.__proto__ = fun.prototype; Далее вызывается функция fun и этот объект передается ей в качестве this. Как при вызове fun.apply(o) |
А откуда у нашей fun взялся метод apply?
Все оттуда же. Функция - объект Любая функция создается с помощью (неявного) вызова new Function() Мы написали function fun() {...} На самом деле получили var fun = new Function(....) Function - встроенная функция JS. Как и любая функция она содержит свойство prototype Function.prototype = { constructor: Function, // и прочие методы apply: function () {...}, call: function () {...}, bind: function () {...}, ..... } Когда вызвался fun = new Function (...) как и для всех объектов произошло fun.__proto__ = Function.prototype; Поэтому методы apply, call, bind... стали доступны для fun |
На самом деле все немного сложнее.
У объектов нет никакого свойства __proto__. Есть внутреннее, недоступное из программ свойство [[Prototype]]. А __proto__ это getter/setter из Object.prototype - системные функции JS, которые могут получать/менять [[Prototype]] объектов. Они доступны из объектов через цепочку прототипов. Если она не нарушена. let op = { x: 1, y: 2 }; let o ={}; o.__proto__ = op; console.log (o.__proto__); // {x:1, y:2} здесь идет обращение к Object.prototype get __proto__ console.log (o.x, o.y); // 1 2 это из прототипа o.__proto__ = null; console.log (o.x, o.y); // undefined undefined т.к. нет прототипа o.__proto__ = op; console.log (o.__proto__) // по прежнему {x:1, y:2} но это не прототип! это обычное свойство __proto__ console.log (o.x, o.y); // и по прежнему undefined undefined т.к. нет прототипа. И никогда не будет. Написав o.__proto__ = null, мы нарушили цепочку прототипов. Из нашего объекта теперь невозможно добраться до Object.prototype и нет доступа к setter __proto__. Поэтому, когда мы снова пишем o.__proto__ = op, то не меняем прототип [[Prototype]], а просто создаем обычное свойство с именем __proto__. Оно ссылается на op, но это не имеет никакого отношения к прототипу объекта |
>>
Цитата:
Приведенный пример кода состоит из трех строк каждая из которых является выражением. 1. используется функциональное выражение (function fun (){}) для создания функционального объекта и присваивание(взятие ссылки) его переменной ff. ff хранит ссылку на функциональный объект который можно вызвать как функцию используя эту ссылку ff. 2. Вызов по ссылке(ff) функции(fun) как конструктора для нового объекта типа (fun) и сохранение полученного нового объекта в переменную f 3. команда консоли вывести объект на который ссылается переменная f. >> Конструктор как выглядит здесь? Здесь в роли конструктора выступает функция fun (function fun (){}; ) Любой функциональный объект в JavaScript может быть использован как функция конструктора. В JavaScript нет разницы между функциями и конструкторами. >> Он создается для потомков? Для создания потомков конструктор не нужен т.к. ему нечего и незачем конструировать. Наследникам для получения наследства в виде свойств и методов достаточно просто стать наследниками. т.е. указать ссылкой на свой прототип. ИМХО твоя проблема в том что абстракции и понятия используемые в компилируемых языках где требуются описания различных классов объектов и описанию по их построению(конструкторы/деструкторы) ты пытаешься использовать в JavaScript и приходишь к противоречиям и непоняткам ставящим тебя в тупик непонимания. JavaScript это другой язык построенный на отличающихся абстракциях и понятиях. |
Часовой пояс GMT +3, время: 19:49. |