Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 26.11.2014, 02:52
Кандидат Javascript-наук
Отправить личное сообщение для SunnyDay Посмотреть профиль Найти все сообщения от SunnyDay
 
Регистрация: 22.09.2008
Сообщений: 111

Магия с JS Proxy
При разработке фреймворка для XUL-UI (для Firefox плагинов) - встал вопрос о том, чтобы представлять элемент(там это чекбокс, селект, групбокс например) и группу тех-же элементов (массив тобишь) одним и тем же интерфейсом. При том что все элементы хоть и наследуются от от одного базового, но имеют разные прототипы(классы). То есть должны работать простые примеры:

element.attr('class','some');//устанавливает класс одного элемента в some
[element1, element2, element3].attr('class','some');//устанавливает класс 3-х элементов в some
//метода val - например нет в базовом классе этого фреймворка, потому что не все имеют значения - логично вроде
element.val();//возвращает значение элемента
[element1, element2, element3].val();//возвращает массив, каждый элемент которого соответствует значению каждого элемента в исходном массиве
[element1, element2].find('.some').attr('atr','atrVal');//в 2-х элементах находим все дочерние элементы с классом some и присваиваем им некий аттрибут


Заворачивать в один класс работу как со множеством, так и с одним элементов( как делает jQuery) - было бы накладно по архитектуре, и грозило бы потерей гибкости. Но оставлять как в mootools - аля забудь про множества, тоже неприемлемо. Очень быстро нагуглилось классное решение вопроса - Proxy https://developer.mozilla.org/en-US/..._Objects/Proxy . Создал обёрточный метод который при попытке вызова любого метода множества - вызывает его у каждого элемента множества, и формирует резутат-массив, каждый элемент которого соответствует результату вызванного множества:


//функция-проксер, проксирующая массив
var Multiplicity = function(in_array){
    var proxy = new Proxy(in_array,{
        get: function(target, name) {
          if  (name in target) return target[name];
          var proxyMethod = function(){
            var proxyResult = [];
            for(var i=0;i<target.length;i++){
                if (!target[i]) continue;
                if (typeof target[i][name] == 'function'){
                    proxyResult.push(target[i][name].apply(target[i], arguments));
                }else if (typeof target[i][name] != 'undefined'){
                    proxyResult.push(target[i][name]);
                }else{
                    proxyResult.push(undefined);
                }
            }
            return Multiplicity(proxyResult);
          }
          return proxyMethod;
        }
    });
    return proxy;
};

//ПРИМЕР использования проксера массивов
var cls = function(){
  this.f = function(){return new subCls();};
};
var subCls = function(){
  this.f2 = function(){return Math.random();};
};

Multiplicity([new cls(), new cls()]).f().f2();//выведет массив из двух случайных чисел
Multiplicity([new cls(), new subCls()]).f2();//выведет [undefined, случайное_число]


подход нравится своей волшебной гибкостью(с первого взгляда) - какие бы программисты не дописали методы в классы элементов, Proxy будет их "есть". Но вот вопрос, нет ли в таком подходе подводных камней, да таких что могут потопить UI-фреймворк? Есть ли причины не использовать Proxy кроме того что объект пока по-умолчанию доступен только в Firefox (а в остальных браузерах пока в стадии experimental)?

Последний раз редактировалось SunnyDay, 26.11.2014 в 02:58.
Ответить с цитированием
  #2 (permalink)  
Старый 27.11.2014, 02:20
Аватар для MallSerg
Профессор
Отправить личное сообщение для MallSerg Посмотреть профиль Найти все сообщения от MallSerg
 
Регистрация: 07.03.2011
Сообщений: 1,138

мое скромное мнение
Ответить с цитированием
  #3 (permalink)  
Старый 27.11.2014, 03:01
Аватар для рони
Профессор
Отправить личное сообщение для рони Посмотреть профиль Найти все сообщения от рони
 
Регистрация: 27.05.2010
Сообщений: 33,108


мне вот тут понравилось как одиночный элемент превращается в массив, да и сама обработка каждого элемента ...
Еще один тупой вопрос по наследованию
Ответить с цитированием
  #4 (permalink)  
Старый 07.01.2015, 05:40
Кандидат Javascript-наук
Отправить личное сообщение для SunnyDay Посмотреть профиль Найти все сообщения от SunnyDay
 
Регистрация: 22.09.2008
Сообщений: 111

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

jQuery('.red').find.('div').find('a').css('color','red');


Нужно чтобы работало так-же. Только с той разницей что в jQuery фиксированный класс элемента - не используется наследование, вместо этого плагинизация базового класса. Требуется же использовать наследование, да так что множеству(массиву состоящему возможно из элементов разных классов) можно так-же вызвать через точку методы, описанные хотя-бы в одном элементе множества.

Вобщем да, Proxy - пошло в разработку уже, решили его юзать
Ответить с цитированием
  #5 (permalink)  
Старый 07.01.2015, 05:51
Кандидат Javascript-наук
Отправить личное сообщение для SunnyDay Посмотреть профиль Найти все сообщения от SunnyDay
 
Регистрация: 22.09.2008
Сообщений: 111

рони, кстати, вместо
isset(o, ['a', 'w', 'r', 't', 'y'])

можно по-человечески использовать

typeof o.a.w.r.t.y


если o наследник Proxy.

А так - как делает функция isset вышеприведённая, портит стилистику и читаемость кода.

Правка. нет - вру, typeof - не получится, но просто вместо эксепшена o.a.w.r.t.y может возвращить null например , если o - Proxy .

Последний раз редактировалось SunnyDay, 07.01.2015 в 06:59.
Ответить с цитированием
  #6 (permalink)  
Старый 07.01.2015, 08:08
Аватар для Erolast
Профессор
Отправить личное сообщение для Erolast Посмотреть профиль Найти все сообщения от Erolast
 
Регистрация: 24.09.2013
Сообщений: 1,436

Цитата:
var cls = function(){
this.f = function(){return new subCls();};
};
var subCls = function(){
this.f2 = function(){return Math.random();};
}
Не делай так классы, у тебя каждому инстансу будет присуждаться собственный экземпляр метода, что перерасход памяти. Используй прототип:
var cls = function() {

}
cls.prototype.f = function() {
  return new subCls();
}
Ответить с цитированием
  #7 (permalink)  
Старый 13.01.2015, 03:44
Кандидат Javascript-наук
Отправить личное сообщение для SunnyDay Посмотреть профиль Найти все сообщения от SunnyDay
 
Регистрация: 22.09.2008
Сообщений: 111

Сообщение от Erolast Посмотреть сообщение
Не делай так классы, у тебя каждому инстансу будет присуждаться собственный экземпляр метода, что перерасход памяти. Используй прототип:
var cls = function() {

}
cls.prototype.f = function() {
  return new subCls();
}
спасибо, в курсе. Пример просто лаконичный - с прототипами более громоздко.
Ответить с цитированием
  #8 (permalink)  
Старый 28.01.2015, 03:04
Кандидат Javascript-наук
Отправить личное сообщение для SunnyDay Посмотреть профиль Найти все сообщения от SunnyDay
 
Регистрация: 22.09.2008
Сообщений: 111

Для информации - с JS-Proxy имеется всё-таки один подводный камень: это производительность. Видимо оптимизаторы пока его ещё не так лихо едят. Поясню - если завернуть массив в Proxy и переопределить get (как в примере топика), то в нём сразу же в огромные разы медленнее начинают работать вшитые методы, особенно indexOf . Поэтому не стоит это использовать Proxy больших массивов. Но для небольших массивов, которые не крутятся рекурсивно по 10 раз - самое то)
Ответить с цитированием
Ответ



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

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


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Операционная Система на JS Icat Общие вопросы Javascript 3 17.04.2018 22:54
Вывыод контента через JS inet_boy Элементы интерфейса 0 18.11.2013 03:00
Не получается вставить код js в HTML garmoni Элементы интерфейса 3 05.09.2013 05:56
Вставка кода js с помощью js Alice Общие вопросы Javascript 1 12.06.2013 19:05
Не получается передать переменную из JS в PHP Lion_astana AJAX и COMET 2 23.11.2010 17:23