Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   __proto__ и prototype в JavaScript (https://javascript.ru/forum/misc/81655-__proto__-i-prototype-v-javascript.html)

denis_alekss 06.01.2021 14:12

__proto__ и prototype в JavaScript
 
Зачем нужен prototype в JavaScript?

При создании любого объекта в JavaScript создается новый объект __proto__ в системе который ссылается на функцию(класс) с помощью которого этот объект создан.

При объявлении функции или класса создается также объект с именем prototype.
Он создается для того чтобы потомки функции-классы могли унаследовать его свойства или для того чтобы сделать чисто инициализацию конструктора, которая происходит после new когда объявляется любая функция или класс?

MallSerg 06.01.2021 15:11

https://otvet.mail.ru/question/223341802 =)

denis_alekss 06.01.2021 15:24

Цитата:

Сообщение от MallSerg (Сообщение 532379)

Это мой вопрос на mail.ru А кто-то может дать свой ответ?

Смотрел видео Димыча который ведет уроки в Беларусии по JavaScript, он говорит что при создании функции или класса создается объект prototype, а при создании объекта создается ссылка на этот prototype. А этот человек на маил.ру ответил что ничего не создается. Этот один вопрос.
И второй... Цель создания свойства prototype для функции?
Чтобы инициализировать конструктортой функции которой я придумал после того как я создам объект своего же класса(функции)?

Alexandroppolus 06.01.2021 15:37

https://learn.javascript.ru/prototype-inheritance

denis_alekss 06.01.2021 15:43

Цитата:

Сообщение от Alexandroppolus (Сообщение 532382)

Я прочитал эту статью но там не указан ответ на мой вопрос, там написано как оформлять код, но не написано что происходит при объявлении функции и что происходит при объявлении объекта с __proto__ и prototype и где происходит и зачем конкретно прототайп нужен, статья не отвечает на вопросы на которые я описал выше.

Alexandroppolus 06.01.2021 15:55

Да, про функцию там нет. В след. статье есть
https://learn.javascript.ru/function-prototype

MallSerg 06.01.2021 20:14

>> А этот человек на маил.ру ответил ...
Это был я

>> который ведет уроки по JavaScript ...
На мой скромный взгляд пару часов воды разбавленных вкраплениями чуши и бреда.

Главное в изучении JavaScript научится пользоваться отладчиком что бы проверять и закреплять полученные знания на опыте.

выполни в консоли браузера
ff = function fun (){};
f = new ff();

console.dir(f);

И изучи из чего состоит полученный объект.

Ну и как пример хорошего материала с ютуба правда устарело на кучу лет
https://www.youtube.com/watch?v=a3X9uqCoxKY

denis_alekss 07.01.2021 14:26

Цитата:

Сообщение от MallSerg (Сообщение 532390)
>>
И изучи из чего состоит полученный объект.

ff = function fun (){};
f = new ff();

console.dir(f);

Этот объект состоит из:

1. функции fun
2. конструктора fun
3. __proto__ ссылается на функцию-класс с помощью которого он был создан, то есть на функцию fun.
4. Сама функция fun ссылается на Object.prototype


Конструктор как выглядит здесь? Он создается для потомков?

voraa 07.01.2021 19:03

Цитата:

Сообщение от denis_alekss
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
Цитата:

Сообщение от denis_alekss
Конструктор как выглядит здесь? Он создается для потомков?

конструктор - это сама функция fun.

voraa 07.01.2021 19:28

Тут же нет ничего сложного

Любой объект содержит свойство __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)

voraa 07.01.2021 19:44

А откуда у нашей 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

voraa 07.01.2021 20:58

На самом деле все немного сложнее.
У объектов нет никакого свойства __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, но это не имеет никакого отношения к прототипу объекта

MallSerg 08.01.2021 01:58

>>
Цитата:

Сообщение от denis_alekss
Сообщение от MallSerg
>>
И изучи из чего состоит полученный объект.

ff = function fun (){};
f = new ff();

console.dir(f);
Этот объект состоит из:

1. функции fun
2. конструктора fun
3. __proto__ ссылается на функцию-класс с помощью которого он был создан, то есть на функцию fun.
4. Сама функция fun ссылается на Object.prototype

Я привет пример кода выполнив который в консоли браузера ты должен был получить в ответ объект.

Приведенный пример кода состоит из трех строк каждая из которых является выражением.
1. используется функциональное выражение (function fun (){})
для создания функционального объекта и присваивание(взятие ссылки) его переменной ff.
ff хранит ссылку на функциональный объект который можно вызвать как функцию используя эту ссылку ff.
2. Вызов по ссылке(ff) функции(fun) как конструктора для нового объекта типа (fun) и сохранение полученного нового объекта в переменную f
3. команда консоли вывести объект на который ссылается переменная f.

>> Конструктор как выглядит здесь?
Здесь в роли конструктора выступает функция fun (function fun (){}; )
Любой функциональный объект в JavaScript может быть использован как функция конструктора.
В JavaScript нет разницы между функциями и конструкторами.

>> Он создается для потомков?
Для создания потомков конструктор не нужен т.к. ему нечего и незачем конструировать.
Наследникам для получения наследства в виде свойств и методов достаточно просто стать наследниками.
т.е. указать ссылкой на свой прототип.

ИМХО твоя проблема в том что абстракции и понятия используемые в компилируемых языках где требуются описания различных классов объектов и описанию по их построению(конструкторы/деструкторы) ты пытаешься использовать в JavaScript и приходишь к противоречиям и непоняткам ставящим тебя в тупик непонимания.
JavaScript это другой язык построенный на отличающихся абстракциях и понятиях.


Часовой пояс GMT +3, время: 19:49.