Javascript Object Layout

Далее пойдет речь об иерархии объектов в JavaScript.


JOL

Источник: www.mollypages.org/misc/js.mp

Далее идут выдержки из текста и они могут быть «мутными», поэтому я сразу предлагаю не ругаться, а лучше просто поизучать приведенную диаграмму, ибо ради нее и публикуется статья. Т.е. можно дальше и не читать, но если все таки прочтете и увидете явные несоответствия и сможете их аргументировать, то добро пожаловать на обсуждение в комментариях…

Итак перевод:
— Все экземпляры наследуются от прототипа объекта функции, которая их создала.

— Mozilla/Konqueror имеет встроенное свойство __proto__, которое указывает на прототип объекта функции-создателя.

— Независимо от наличия/отсутствия свойства __proto__, основная идея заключается в том, что все объекты используют прототип объекта на который указывает функция-создатель. Прототип объекта по-умолчанию имеет свойство constructor, указывающее обратно на функцию-создатель прототипа.

— Прототип может быть использован только для унаследованных свойств функции. Сама функция не использует ассоциированный прототип!

function foo() {}; var f1 = new foo();
foo.prototype.x = «hello»;
console.log(f1.x); // hello
console.log(foo.x); // undefined

— Прототип объекта по-умолчанию может быть заменен любым другим объектом, созданным пользователем. Свойство constructor при этом должно быть вручную заменено на другое:

function foo() {}; var f1 = new foo();
console.log('исходное >',f1.constructor, foo.prototype.constructor, foo, f1.constructor === foo, foo.prototype.constructor === foo);

foo.prototype.constructor = Object;
console.log('замена прототипа >',f1.constructor, foo.prototype.constructor, Object, f1.constructor === Object, foo.prototype.constructor === Object);

foo.prototype.constructor = foo
console.log('обратно >',f1.constructor, foo.prototype.constructor, foo, f1.constructor === foo, foo.prototype.constructor === foo);

— все объекты автоматически читают свойства прототипов по цепочке от собственных до родительских.

function foo() { }; f1 = new foo(); f2 = new foo();
foo.prototype.x = «hello»;

console.log(f1.x); // «hello»
console.log(f2.x); // «hello»

f1.x = «goodbye»; // установка f1.x «перекрывает» foo.prototype.x Только для f1

console.log(f1.x); // «goodbye»
console.log(f2.x); // «hello»
delete f1.x // удаление локального свойства
console.log(f1.x) // «hello»… foo.prototype.x обратно «видимо» для f1

// Установка свойства непосредственно в прототип изменяет значение во всех экземплярах.

foo.prototype.x = «goodbye»;
console.log(f1.x); // «goodbye»
console.log(f2.x); // «goodbye»;

На приведенной диаграмме можно увидеть, что:

— Function.__proto__ указывает на Function.prototype. Соответственно: Function.constructor === Function Конструктор функции есть функция.

— Object instanceof Object == true. исходя из того, что Object.__proto__.__proto__.constructor == Object

Но, Foo instanceof Foo == false. Потому, что Foo не существует как конструктор в своей собственной цепочке прототипов.
+1
28 августа 2007, 13:42
17
terloger 9,4

комментарии (20)

0
terloger #
Еще раз повторюсь - не нужно лишней критики и взаимных оскорблений, давайте просто по-обсуждаем. ;)
0
Zeroglif #
Страшно? ;) Картинка мне самому понравилась, только надо было её ещё больше заавангардить, добавив туда все конструкторы. Мои любимые пикчеры находятся здесь (только для людей с крепкой писхикой): http://egachine.berlios.de/embedding-sm-…


Вместо "экземпляры наследуются от прототипа" правильнее "экземпляры наследуют от прототипа".

Вместо "используют прототип объекта на который указывает функция-создатель" правильнее "используют прототип, на который указывает функция-конструктор".

Вместо "функция-создатель" везде по тексту лучше бы "функция-конструктор".

> "Свойство constructor при этом должно быть вручную заменено на другое"

Не обязательно, только если есть в этом острая нужда.
0
gro #
Что означает фраза "Прототип объекта по-умолчанию может быть заменен любым другим объектом" и что иллюстрирует код идущий за ней?
0
terloger #
Фраза хм... корява, но не в ней суть ;) попробуйте в FF пример, там есть и комментарии и в логах консоли можно посмотреть процесс.
0
gro #
Ну, это то да. Просто в чем глубинный смысл изменения свойства constructor прототипа и причем тут "замена прототипа объекта"?
0
terloger #
Глубинный смысл в самом факте замены :) А замена при том, что... посмотрите foo.prototype до и после изменения foo.prototype.constructor = Object;
0
gro #
И что это нам дает? :)
0
terloger #
не знаю.
0
terloger #
вернее применения с налету не вижу, но рассматриваются же не применения, а возможности.
0
gro #
Просто мне показалось, что здесь автор пытается динамически изменить прототип уже созданного объекта, т.е. перекинуть его в другое место в иерархии. Это не так?
0
terloger #
Не знаю, есть предположение, что речь идет о реализации «наследования» типа:
function A() {}
A.prototype = {
x : 5
};

function B() { }

b1 = new B();

B.prototype = new A();
b2 = new B();

console.log(b1.constructor === B, b2.constructor === B, B.prototype); // true, false

B.prototype.constructor = B;

console.log(b1.constructor === B, b2.constructor === B, B.prototype); // true, true

Прототипу B присваивается экземпляр A, при этом, чтобы сохранить конструктор от B приходится вручную его переприсваивать: B.prototype.constructor = B;
+1
Zeroglif #
Замена прототипа - это суть игры в наследование в javascript. Перед тем как создать объект-экземпляр мы можем выстроить цепь объектов-прототипов так, как нам нужно, свойства этих объектов по сути станут свойствами экземпляра(ов). Соответственно, после своего создания объект-экземпляр может при необходимости делегировать сообщения своему предку, тот своему и так далее по цепи...

Ну, а ещё прототип переопределяют просто для банального сокращения записи, чтобы не писать 20 раз foo.prototype.x =..., foo.prototype.y = ... пишут инициализатор объекта foo.prototype = {x: 'preved', y: 'medved'}
0
isapioff #
как-то запутанно, начиная с рисунка. я использую ext js для создания иерархии объектов.
0
terloger #
Но речь же не о библиотеках, я тоже ExtJS использую для наследования. А на счет запутанности... ну.. как есть ;)
0
terloger #
Если я не ошибаюсь, то на диаграмме не хватает еще стрелочек "-- constructor -->" от объектов-экземпляров к объектам-конструкторам.
+1
gro #
Если под этой стрелочкой подразумевается свойство "constructor" объекта-экземпляра, то такого свойства не существует.
0
terloger #
Да, это моя глупость. Черт, логично, код
function A() {}; var a = new A();
console.log(a.constructor === A);
выдаст true, но из-за того, что конструктор найдется по цепочке у объекта-прототипа.
0
develop7 #
Наблы 39 и 40. Затрагиваемые вопросы там также освещены.
ИМО, полезно не читавшим. Наблы выше/стандарт ECMAScript/толстые книги по.
+1
terloger #
Читать нужно не «наблы», а обсуждение в форуме, иначе путаница гарантирована. Читать посты Zeroglif-a, как самые доходчивые по сути вопроса.
Кстати, толстые книги не катят ибо 99% из них — это полное г.
0
Zeroglif #
Хех, за "самые доходчивые" спасибо, если кому поможет, то это здесь: http://forum.dklab.ru/viewtopic.php?p=10…

Подавляющее большинство книг по javascript действительно плОхи, и даже не в плане освещения прототипов и наследования, а вообще, в целом. Причём нынешние современные стали ещё хуже. Раньше было много базиса и мало чего-то более глубокого, сейчас - мало базиса, куча ошибок, ужасная терминология и претензия на super-mega-advanced...

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.