Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 03.10.2011, 10:49
Аватар для GuardCat
Просто любитель
Отправить личное сообщение для GuardCat Посмотреть профиль Найти все сообщения от GuardCat
 
Регистрация: 13.09.2011
Сообщений: 300

Prototype. Одноблочное определение псевдокласса. Литеральная форма не робит. Почему?
Мне не очень нравятся многоблочные определения псевдоклассов. Т.е. когда вначале определяют класс, блок закрывают, а затем определяют его прототип. Я решил попробовать определить прототип прямо в блоке класса. И столкнулся с полтергейстом:
Создан простой класс, в котором есть прототипная переменная, общая для всех экземпляров класса. Вызывается, через один экземпляр, функция, которая увеличивает общую переменную на 1. Затем выводится значение общей переменной для другого экземпляра.
<html><body>
<script>
function Test()
{
	Test.prototype.data=1;
	Test.prototype.f=function()
	{
		Test.prototype.data++;
	}
}


test1=new Test;
test2=new Test;
test1.f();
document.write("test2.data=",test2.data,"<br>");
</script>
Всё верно, общая переменная поменялась — выводит: test2.data=2.

Отлично! Пробуем оптимизировать:
<html><body>
<script>
function Test()
{
	Test.prototype=
	{
		data:1,
		f:function()
		{
			Test.prototype.data++;
		}
	}
}


test1=new Test;
test2=new Test;
test1.f();
document.write("test2.data=",test2.data,"<br>");
</script>

Получаем: Uncaught TypeError: Object #<Test> has no method 'f'. WTF?!!

А если так:
<html><body>
<script>
function Test(){}
Test.prototype=
{
	data:1,
	f:function()
	{
		Test.prototype.data++;
	}
}

test1=new Test; 
test2=new Test;
test1.f();
document.write("test2.data=",test2.data,"<br>");
</script>
То работает! Но опять разбиваем на два блока верхнего уровня =(.

Вопросы:
  1. Почему литеральная запись объекта внутри блока определения класса не работает, но работает присвоение там же но по полям? (Кстати с with внутри класса тоже не робит). Чем отличается присвоение по полям от литеральной записи?
  2. Почему, в таком случае, литеральная запись работает вне блока определения класса?
Поясните, кто знает механику работы объектов, я что-то не догоняю.
Ответить с цитированием
  #2 (permalink)  
Старый 03.10.2011, 11:41
Аватар для Riim
Рассеянный профессор
Отправить личное сообщение для Riim Посмотреть профиль Найти все сообщения от Riim
 
Регистрация: 06.04.2009
Сообщений: 2,379

Когда во втором примере ты пишешь:
Сообщение от GuardCat
test1=new Test;
this.__proto__ внутри конструктора начинает ссылаться на Test.prototype. А дальше ты бац и заменяешь Test.prototype на новый объект, но this.__proto__ по-прежнему ссылается на старый объект, в котором метода f нет. Вот в ошибке и написано, что его нет. В первом примере ты изменяешь уже существующий объект, и т. к. на него ссылаются и this.__proto__ и Test.prototype, изменения видны в обоих.


Сообщение от GuardCat
Мне не очень нравятся многоблочные определения псевдоклассов. Т.е. когда вначале определяют класс, блок закрывают, а затем определяют его прототип
прототип будет .... , короче, не надо так, бяка.

Последний раз редактировалось Riim, 03.10.2011 в 11:45.
Ответить с цитированием
  #3 (permalink)  
Старый 03.10.2011, 11:52
Аватар для GuardCat
Просто любитель
Отправить личное сообщение для GuardCat Посмотреть профиль Найти все сообщения от GuardCat
 
Регистрация: 13.09.2011
Сообщений: 300

Спасибо, Riim. Стало понятнее. Про бяку, раскройте тему, пожалуйста.
Вы имеете ввиду, что не следует определять прототип литерально, заменяя объект на свой (это теперь понятно)?
Тогда вопрос, внутри определения класса можно (не бяка ли) трогать прототип за поля, не заменяя объект или нужно делать это за пределами определения класса?
Или вообще размещать переменные в прототипе моветон и надо использовать поля класса?

Пристрелите во мне быдлокодера =)

Последний раз редактировалось GuardCat, 03.10.2011 в 12:21.
Ответить с цитированием
  #4 (permalink)  
Старый 03.10.2011, 12:40
Аватар для Riim
Рассеянный профессор
Отправить личное сообщение для Riim Посмотреть профиль Найти все сообщения от Riim
 
Регистрация: 06.04.2009
Сообщений: 2,379

Сообщение от GuardCat
внутри определения класса можно (не бяка ли) трогать прототип за поля
конечно можно, просто то, что более-менее статично лучше определить один раз, так оно будет общее для всех экземпляров. А то, что определяется внутри конструктора, создается каждый раз, а это расход памяти, теряется одно из преимуществ прототипного ООП над обычным.


Сообщение от GuardCat
Мне не очень нравятся многоблочные определения псевдоклассов. Т.е. когда вначале определяют класс, блок закрывают, а затем определяют его прототип
а так вообще все много-много раз создается.

Последний раз редактировалось Riim, 03.10.2011 в 12:42.
Ответить с цитированием
  #5 (permalink)  
Старый 03.10.2011, 12:51
Новичок на форуме
Отправить личное сообщение для Kolyaj Посмотреть профиль Найти все сообщения от Kolyaj
 
Регистрация: 19.02.2008
Сообщений: 9,177

Сообщение от GuardCat
Мне не очень нравятся многоблочные определения псевдоклассов. Т.е. когда вначале определяют класс, блок закрывают, а затем определяют его прототип.
https://github.com/Kolyaj/CrossJS/bl...unction.js#L97
var MyClass = AnotherClass.inherit({
    constructor: function() {
        MyClass.superclass.constructor.apply(this, arguments);
        this.a = 5;
    },

    method1: function() {
        alert('method1');
    },

    method2: function() {
        alert('method2');
    }
});
Ответить с цитированием
  #6 (permalink)  
Старый 03.10.2011, 13:18
Аватар для GuardCat
Просто любитель
Отправить личное сообщение для GuardCat Посмотреть профиль Найти все сообщения от GuardCat
 
Регистрация: 13.09.2011
Сообщений: 300

Сообщение от Riim Посмотреть сообщение
...

а так вообще все много-много раз создается.
Вкурил. И правда, на то он и конструктор.

Kolyaj, спасибо. Только я не настолько крут пока, чтобы понять, что происходит в библиотеке, даже несмотря на комментарии. Сохранил. Буду разбираться.
Ответить с цитированием
  #7 (permalink)  
Старый 03.10.2011, 13:46
Аватар для Riim
Рассеянный профессор
Отправить личное сообщение для Riim Посмотреть профиль Найти все сообщения от Riim
 
Регистрация: 06.04.2009
Сообщений: 2,379

Сообщение от Riim
теряется одно из преимуществ прототипного ООП над обычным
кстати, а это действительно преимущество? А то я где-то мельком услышал, что в обычном ООП все для экземпляра каждый раз создается, в том числе то, что вне конструктора описано. Сейчас вот подумал, а что мешает в обычном ООП сделать механизм подобный тому, что в js? Кто-нибудь знает?
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск