Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 13.01.2014, 02:45
Аспирант
Отправить личное сообщение для Antonius Посмотреть профиль Найти все сообщения от Antonius
 
Регистрация: 30.11.2013
Сообщений: 42

Модификация прототипа «по требованию» — плюсы, минусы, подводные камни
Решаю такую задачу.

Есть относительно большая структура данных, к которой происходит обращение из одного метода объекта. Поскольку обращений при использовании может не быть вовсе, не хочется инициализировать структуру просто так. Хочется инициализировать при первом вызове метода. При этом хочется, чтобы все созданные впоследствие объекты этого типа уже могли использовать эти данные.

Сейчас я это делаю так:
MyObj.prototype.method = function() {
    if (typeof this._data != 'object') {
        this.constructor.prototype._data = {};
        // инициализация данных
    }

    // обращение к данным
};


Но ввиду неопытности и плохого понимания особенностей работы js хочу спросить — не стреляю ли я себе в ногу?

Не хочется привязываться к имени конструктора. Вполне может оказаться, что он еще будет переименован.

Меня смущает ситуация, если пользователь скрипта будет создавать свои объекты, наследуясь от моего. Тут, похоже, этот подход сломается. Если базовый класс уже проинициализировал данные — все хорошо, метод увидит, что они есть в цепочке прототипов, и успокоится. Но если метод будет вызван у класса-потомка, то данные будут инициализированы именно у него, а класс-предок о них ничего не узнает, верно? Можно, конечно, не заморачиваться по этому поводу, но если есть способ сделать надежнее — подскажите, пожалуйста.

А может я вообще неправильно подхожу к проблеме, и есть уже существующие проверенные способы добиться того, что мне нужно. Буду благодарен за разъяснения или ссылки.

Спасибо.
Ответить с цитированием
  #2 (permalink)  
Старый 13.01.2014, 16:29
Аспирант
Отправить личное сообщение для Antonius Посмотреть профиль Найти все сообщения от Antonius
 
Регистрация: 30.11.2013
Сообщений: 42

Пока склоняюсь вместо `this.constructor` использовать все-таки имя конструктора. Вроде неприятностей создать не должно, а проблему при наследовании решает.
Ответить с цитированием
  #3 (permalink)  
Старый 13.01.2014, 17:24
Профессор
Отправить личное сообщение для Яростный Меч Посмотреть профиль Найти все сообщения от Яростный Меч
 
Регистрация: 12.04.2010
Сообщений: 557

Сообщение от Antonius
Но если метод будет вызван у класса-потомка, то данные будут инициализированы именно у него, а класс-предок о них ничего не узнает, верно?
this._data увидит значение в любом из прототипов цепочки.

Тут другой момент. Сначала надо разобраться, действительно ли _data должна быть в прототипе. Ведь в этом случае оно будет общее для всех экземпляров. Если это неправильно, то лучше присваивать в объект, а не в прототип: this._data = {}; - это будет работать одинаково для класса-предка и класса-потомка (я говорю о типе объекта).

Ну а если _data и вправду должна быть общей, то разница в работе будет: при вызове метода для объекта класса-предка создастся общая _data для всех, а в случае класса-потомка - только для классов-потомков, предки потом могут создать свою _data. Потому в этом случае правильнее явно указать имя класса:
MyObj.prototype._data = {};

Последний раз редактировалось Яростный Меч, 13.01.2014 в 17:50.
Ответить с цитированием
  #4 (permalink)  
Старый 13.01.2014, 19:39
Аспирант
Отправить личное сообщение для Antonius Посмотреть профиль Найти все сообщения от Antonius
 
Регистрация: 30.11.2013
Сообщений: 42

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

Ситуация в целом такая: в прототипе в одном из полей есть объект с парами ключ-значение, которые представляют собой что-то вроде словаря, этот объект задан литералом и меняться, скорее всего, не будет (не могу придумать ситуацию, когда это понадобится). Типичное использование — взятие значения по ключу.

Тот метод, о котором я говорю, ищет имя ключа по значению. И чтобы избежать постоянного обхода объекта и поиска значений я хочу при первом обращении создавать «перевернутую» копию этого объекта, где ключами будут значения, а значениями — имена ключей из первого словаря. Таким образом при последующих обращениях можно будет снова обращаться просто по ключу как к полю объекта.

Поэтому и хочу сохранять данные в прототипе корневого класса — они общие для всех объектов этого типа. Если потомку понадобится модифицировать эти данные — он вполне сможет создать их копию у себя и модифицировать ее как угодно.

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

Вообще, такой подход как у меня имеет право на жизнь?
Ответить с цитированием
  #5 (permalink)  
Старый 13.01.2014, 21:30
Аватар для nerv_
junior
Отправить личное сообщение для nerv_ Посмотреть профиль Найти все сообщения от nerv_
 
Регистрация: 29.11.2011
Сообщений: 3,924

Сообщение от Antonius
Есть относительно большая структура данных, к которой происходит обращение из одного метода объекта. Поскольку обращений при использовании может не быть вовсе, не хочется инициализировать структуру просто так. Хочется инициализировать при первом вызове метода. При этом хочется, чтобы все созданные впоследствие объекты этого типа уже могли использовать эти данные.
синглтон / singleton
и можешь хранить свой большой объект где угодно и обращаться как захочешь
__________________
Чебурашка стал символом олимпийских игр. А чего достиг ты?
Тишина - самый громкий звук
Ответить с цитированием
  #6 (permalink)  
Старый 13.01.2014, 21:41
Аспирант
Отправить личное сообщение для Antonius Посмотреть профиль Найти все сообщения от Antonius
 
Регистрация: 30.11.2013
Сообщений: 42

Спасибо, читаю эту тему.

И вот сразу не пойму, в чем тонкости. Можете привести ссылку, где этот вопрос разбирается более-менее просто и понятно?

Я в любом случае продолжу искать сам, но пока не очень продвинулся в понимании

Пока не понял, чем это отличается от того, что я хочу сделать принципиально, какие даст преимущества.

Последний раз редактировалось Antonius, 13.01.2014 в 21:47.
Ответить с цитированием
  #7 (permalink)  
Старый 13.01.2014, 21:48
Аватар для nerv_
junior
Отправить личное сообщение для nerv_ Посмотреть профиль Найти все сообщения от nerv_
 
Регистрация: 29.11.2011
Сообщений: 3,924

http://www.dofactory.com/javascript-...n-pattern.aspx
__________________
Чебурашка стал символом олимпийских игр. А чего достиг ты?
Тишина - самый громкий звук
Ответить с цитированием
  #8 (permalink)  
Старый 16.01.2014, 04:39
Аспирант
Отправить личное сообщение для Antonius Посмотреть профиль Найти все сообщения от Antonius
 
Регистрация: 30.11.2013
Сообщений: 42

Спасибо, наконец-то добрался и прочитал, смысл понял, но в моем случае пожалуй незачем так уж стараться, мой вариант кажется адекватным задаче, но в будущем когда-нибудь обязательно пригодится и прочитанное.
Ответить с цитированием
Ответ



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

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