Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Понимание ООП в JavaScript (https://javascript.ru/forum/misc/3070-ponimanie-oop-v-javascript.html)

Gvozd 15.03.2009 18:57

блин, да нет же.
интересно где я не так начал объяснять.

__proto__(или же [[prototype]], что есть одно и тоже) и prototype - это разные вещи.


__proto__(или же [[prototype]]) это и есть прототип объекта.
если у объекта не находится какое-то свойство, то оно начинает искатся в его прототипе.затем в прототипе прототипа.и так пока не дойдет до самого верхнего прототипа - объекта [object Object]

prototype - это такое свойство у функции-конструктора, которое определяет какой прототип будет у объектов создаваемых этим конструктором.НО, это НЕ ПРОТОТИП самой функции.
Прототипом самой функции является пустая функция function(){}

ТО ЕСТЬ ЭТО НЕВЕРНО:
Цитата:

Сообщение от kefi
прототип объекта - это объект.prototype

на самом деле правильно
Цитата:

прототип объекта - это объект.[[prototype]](или же объект.__proto__). и это является функция_конструктор.prototype
ТАКЖЕ НЕВЕРНО:
Цитата:

Сообщение от kefi
прототип объекта - это прототип его конструктора, т.е. объект.constructor.prototype

на самом деле правильно:
Цитата:

прототип объекта - это свойство prototype(А НЕ ПРОТОТИП) его конструктора, т.е. объект.constructor.prototype
на примере:
//constr- функция-конструктор.все что будет объявлено посредством (new constr()) будет иметь тип constr
var constr = function()
	{this.a = 1;}
//var constr = new Function("this.a = 1;") // <- или так 
//Function - функция-конструктор для всех прочих функций

alert(constr.__proto__==Function.prototype);//TRUE
//прототипом функции constr(а она помимо всего прочего также является объектом) является объект, заданный в свойстве prototype ее конструктора
alert(constr.__proto__);//function(){}
//прототипом функции constr является просто пустая функция.
//у всех функций один общий прототип.этот прототип является объектом-пустой функцией

//------------------------------------------------------------------------------------------------
//вот мы задаем, что у всех объектов, созданных при помощи new constr() будет общий прототип.
//прототип функции от это не меняется
constr.prototype={'b':2}

//а вот мы создаем объект при помощи нашего конструктора
obj=new constr()

alert(obj.__proto__==constr.prototype);//TRUE
//прототипом объекта, созданного при помощи конструктора constr является объект, заданный в свойстве prototype его конструктора

alert(obj.__proto__);// этот объект: {'b':2}

alert('obj.a='+obj.a)//1 .свойство берется из самого объекта
alert('obj.b='+obj.b)//2 .свойство берется из прототипа объекта

obj2=new constr()//создадим еще один объект
//для него пока что свойства идентичны
alert('obj2.a='+obj2.a)//1 .свойство берется из самого объекта
alert('obj2.b='+obj2.b)//2 .свойство берется из прототипа объекта
//переопределим его свойства:

obj2.a=11
obj2.b=12
//посмотри как это повлияло на первый и второй объекты:
alert('obj.a='+obj.a)//1 .свойство берется из самого объекта.никакого влияниея второго объекта
alert('obj.b='+obj.b)//2 .свойство берется из прототипа объекта.никакого влияниея второго объекта
alert('obj2.a='+obj2.a)//11 .свойство берется из самого объекта
alert('obj2.b='+obj2.b)//12 .свойство берется из самого объекта.прототип остался неизменным
//как видим изменение своства b второго объекта никак не повлияло на прототип, и на первый объект.
//ну, совсем никак


//теперь изменим свойство b у ихнего прототипа:
constr.prototype.b=22
alert('!obj.b='+obj.b)//22
alert('!obj2.b='+obj2.b)//12
//как видим изменение прототипа затронуло только первый объект
//потому что у первого свойство b не было переопределено .а у второго было.
//поэтому первый все еще берет свойство из протипа, а вот второй берет уже собственное свойство b, которое мы назначили выше

//попробуем поменять свойство prototype у функции-конструктора
constr.prototype={'b':32}
alert('obj.b='+obj.b)//22
alert('obj2.b='+obj2.b)//12
//как видим смена свойства prototype у функции-конструктора никак не сказалась на УЖЕ созданных объектах.
//зато все последующие созданные объекты будут иметь НОВЫЙ прототип, никак не связанный с прототипом старх объектов

obj3=new constr()
alert('obj3.b='+obj3.b)//33.это свойство его прототипа.но не прототипа предыдущих объектов
alert([ obj.__proto__== obj2.__proto__,
				obj3.__proto__== obj.__proto__,
				obj3.__proto__== obj2.__proto__ ])//TRUE,FALSE,FALSE
//как видим у первых двух объектов прототип совпадает между собой.
//а  вот у третьего не совпадает ни с прототипом первого, ни с прототипом второго


PS запускать для наглядности в Mozilla
также будет легче, если вы поставите себе firebug, и замените все alert на console.log

Gvozd 15.03.2009 19:00

надеюсь этот пример разъяснит вам на пальцах, как это все работает.
я старался

Dmitry A. Soshnikov 15.03.2009 19:27

Цитата:

Сообщение от Gvozd
alert('obj2.b='+obj2.b)//12 .свойство берется из прототипа объекта

Опечатался. Свойство берется уже из объекта.

Молодец, хорошо описал. ;)

Gvozd 15.03.2009 19:34

Dmitry A. Soshnikov,
спасибо.исправил

kefi 15.03.2009 20:56

2 Gvozd > Исправьте и у меня , если что далее неверно :

Прототип(тип или класс родителя) объекта - это свойство prototype конструктора объекта ( объект.constructor.prototype ).

На примере встроенного объекта Array можно сделать следующие высказывания:

1) Array.prototype // - ссылка на прототип(или что то же самое тип родителя) объектов, создаваемых с помощью конструктора Array, который сам является объектом типа Function ; Т.е. :
Function===Array.constructor // - конструктор Array - есть Function (или , что то же самое, - его тип есть Function)
Function.prototype===Array.constructor.prototype // - тип родителя объекта Array (являющегося конструктором) тоже определяется через свойство prototype его конструктора ( которое == function prototype() {[native code] } )

2) Array.prototype.constructor===a.constructor // - ссылка на конструктор объектов а, которые имеют тип Array (,где var a=new Array() )

3) Array.prototype===a.constructor.prototype // - прототип (тип родителя) объекта а [strike](== function Array() { [native code] } )[/strike]

4) Array===a.constructor // - [strike]тип (класс) объекта а [/strike]- объект-конструктор объекта а ( == function Array() { [native code] } )

Gvozd 15.03.2009 22:04

Цитата:

Сообщение от kefi
Прототип(тип или класс родителя) объекта - это свойство prototype конструктора объекта ( объект.constructor.prototype )

во первых в JS Нету понятия класс(хотя это можно симитировать)
во вторых тип объекта и прототип - разные вещи.
тип объекта определяется каким конструктором он был создан.
а прототип свойством prototype конструктора, на момент создания объекта
ну, и в третьих родителем объекта является его прототип, а не его конструктор
прототип объекта-это не тип и не класс объекта, а объект, постоянно висящий в памяти, и который можно считать родителем этого объекта
----------------------------------------------------------------------
Цитата:

Сообщение от kefi
1) Array.prototype // - ссылка на прототип(или что то же самое тип родителя) объектов, создаваемых с помощью конструктора Array,
прототип которого Function;

не совсем так:
у Array прототип не Function, а объект созданный с помощью Function
Array.__proto__!=Function
Array.__proto__==(function(){})//тут на самом деле будет FALSE.но суть примерно такая, что прототип конструктора Array - пустая функция

Таким образом Function - конструктор конмтруктора Array, а пустая функция(не любая, а вполне такая определенная, висящая в памяти со старта скрипта, и созданная интепретатором) яляется прототипом конструктора Array
----------------------------------------------------------------------
Цитата:

Сообщение от kefi
2) Array.prototype.constructor===a.constructor // - ссылка на конструктор объектов а, которые имеют тип Array (,где var a=new Array() )

это равенство более полно выглядело бы так:
Array.prototype.constructor===a.constructor===Arra y
то есть конструктор у объекта a и у его прототипа одинаков, и это есть функция Array
----------------------------------------------------------------------
Цитата:

Сообщение от kefi
3) Array.prototype===a.constructor.prototype // - прототип (тип родителя) объекта а (== function Array() { [native code] } )

Array.prototype - прототип объекта a(но тип родителя)
Array - тип родителя объекта a( и при этом тип самого объекта a)
Цитата:

Сообщение от kefi
Array.prototype===a.constructor.prototype (== function Array() { [native code] } )

Это вообще не верно
Array.prototype===a.constructor.prototype == new Array()//опять-таки тут будет на самом деле FALSE. по сути дела заместо (new Array()) должен быть так же висящий в памяти объект типа Array
----------------------------------------------------------------------

половина исправлений была скорее на терминологию

Zeroglif 15.03.2009 22:45

Количество слов "prototype" в ветке взрывает мозг. :dance:

сорри за оффтоп

Gvozd 15.03.2009 23:02

Zeroglif,
ты мне тут это.того.
не загаживай такую прелестную ветку оффтопом:rolleyes:
PS на самом деле мне эта тема очень нравится.
гораздо приятней помочь человеку разобратся в такой довольно нелегкой вещи как прототипирование(я сам статью Кантора перечитывал раза три, прежде чем до меня тогда начало доходить.и вообще, я сперва думал, что prototype==[[prototype]]), чем заставлять людей хоть немного потрудится самим, после того как объясниш ему алгорит простейшей задачи.
во всяком случае тут видна усердная работа человека и стремление разобратся, а не получить решение конкретной задачи "на блюдечке"

Zeroglif 15.03.2009 23:09

Цитата:

Сообщение от Gvozd
я долгое время думал, что prototype==[[prototype]]

Чаще всего так и есть. ;)

Gvozd 15.03.2009 23:13

Zeroglif,
вообще-то я думал, что
obj.prototype==obj.[[prototype]]

ну или как-то так.
уже точно не помню, что творилось у менгя в голове
но точно помню, как три или четыре раза перечитывал статью
короче, мне эта тема не сразу, и не так просто далась


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