Я знаю про Backbone.js и про Knockout.js
Просто иногда хочется чего-то значительно меньшего.
1. Введение. О чем речь, какова предметная область. Какая существует проблема.
О чем речь: есть JavaScript, «сферический, в вакууме».
Предметная область: объекты и их свойства, то, что задается приведенными ниже способами.
где свойства, соответственно:
Какая существует проблема:
1. Есть вот такие вот объекты, у них есть эти самые свойства.
2. Хочется узнать, когда свойство было изменено ( часть MVVM pattern )
3. И, соответственно, подписаться на это изменение.
UPD 1 — Пример в работе, спасибо alist, за очень, по моему мнению, важный комментарий ниже.
2. Подробно, что за задача которую нужно решить.
Собственно, это и есть задача, подписаться на изменения свойств, и вызвать функцию, которая может что-нибудь сделать с этим новым значением свойства. Пусть на самом «элементарном» уровне. Достаточно отслеживать изменение простых свойств: чисел, строк, boolean. Т.е., свойства с вложенными массивами, объектами и функциями нам может быть даже и не нужны.
Даже такое простое «подписывание с callback» на такие простые свойства уже может существенно сократить время разработки. Например, можно навесить триггер на получение новых данных из socket, или подписаться на изменение какого-нибудь свойства в модели, которое визуально выведено на страничку.
3. Аналоги. Существующие решения проблемы, какие у них плюсы-минусы
Сильно много не искал, для Тяжелых вещей ведь достаточно Backbone.js и Knockout.js.
Так что это ни в коем случае им не аналог, так, заглушка для элементарных операций, или просто если эти библиотеки «не участвуют» в коде.
4. Описание решения проблемы.
На коленке за ночь пересобрал две функции, способные, соответственно, разными способами с тем или иным успехом со своими плюсами и минусами решить подобную задачу:
warp ( obj, prop, setcallback, interval )
observe( value, setcallback )
Плюс observe ():
— короткий синтаксис
— никаких таймаутов, геттеров и прочего
— элементарен как топор, будет работать везде где есть JS
Минус observe (): вместо просто свойства будет функция, и об этом нужно помнить.
Плюс warp(): реально подписывается на реальное свойство, т.е. можно просто присваивать новые значения свойству внутри объекта.
Минусы warp():
— объемный синтаксис.
— если браузер «старый», без геттеров и сеттеров, то интервалы отслеживания изменений будут сильно его грузить при отсутствующем «interval».
— я не проверял, обнуляется ли интервал при удалении свойства, по идее — должен.
5. Вывод. Почему это стоит использовать и когда, а когда не стоит.
Это можно использовать, если нужно сделать что-то простое, не требующее «концепции».
Всё очень непритязательно:
warp — подписывается на свойства с callback'ом на set.
observe — подменяет свойство функцией с callback'ом на set.
Небольшое объяснение под этой плашкой кода.
Пример достаточно вставить в пустой HTML файл.
UPD 0 — краткая справка.
Попытаюсь рассказать как я это использую, по шагам.
1. Пусть есть какой-то объект.
2. У него есть какое-то свойство, строка, число или boolean.
3. Я хочу знать когда оно изменится, и подписаться на это изменение с callback'ом, который примет новое value.
Для этого я использую warp ( obj, prop, setcallback, interval )
где:
obj — тот самый объект
prop — то самое свойство
setcallback — тот самый callback, который получит измененное значение.
interval — если хочу, чтобы callback отработал с задержкой.
Это то, что касалось warp.
То что касается observe: ситуация аналогичная, но мне достаточно не действительно слушать свойство а подменить его функцией.
Тогда:
1. Есть объект
2. Есть свойство
3. Я подменяю его функцией посредством
observe( value, setcallback )
после чего установка нового значения будет выглядеть как
obj.my_property ( 'new value' );
а чтение этого же значения как obj.my_property ( );
Читабельные сорцы про геттеры и сеттеры:
http://robertnyman.com/javascript/javascript-getters-setters.html#regular-getters-and-setters
https://developer.mozilla.org/en/JavaScript/Reference/Operators/get
https://developer.mozilla.org/en/JavaScript/Guide/Working_with_Objects#Defining_Getters_and_Setters
Но все должно работать и без этих feature.
Просто иногда хочется чего-то значительно меньшего.
1. Введение. О чем речь, какова предметная область. Какая существует проблема.
О чем речь: есть JavaScript, «сферический, в вакууме».
Предметная область: объекты и их свойства, то, что задается приведенными ниже способами.
var obj = new Object(); var obj = {};
где свойства, соответственно:
obj.prop = 111; obj = { "prop1" : "value1" "prop2" : 2 }
Какая существует проблема:
1. Есть вот такие вот объекты, у них есть эти самые свойства.
2. Хочется узнать, когда свойство было изменено ( часть MVVM pattern )
3. И, соответственно, подписаться на это изменение.
UPD 1 — Пример в работе, спасибо alist, за очень, по моему мнению, важный комментарий ниже.
2. Подробно, что за задача которую нужно решить.
Собственно, это и есть задача, подписаться на изменения свойств, и вызвать функцию, которая может что-нибудь сделать с этим новым значением свойства. Пусть на самом «элементарном» уровне. Достаточно отслеживать изменение простых свойств: чисел, строк, boolean. Т.е., свойства с вложенными массивами, объектами и функциями нам может быть даже и не нужны.
Даже такое простое «подписывание с callback» на такие простые свойства уже может существенно сократить время разработки. Например, можно навесить триггер на получение новых данных из socket, или подписаться на изменение какого-нибудь свойства в модели, которое визуально выведено на страничку.
3. Аналоги. Существующие решения проблемы, какие у них плюсы-минусы
Сильно много не искал, для Тяжелых вещей ведь достаточно Backbone.js и Knockout.js.
Так что это ни в коем случае им не аналог, так, заглушка для элементарных операций, или просто если эти библиотеки «не участвуют» в коде.
4. Описание решения проблемы.
На коленке за ночь пересобрал две функции, способные, соответственно, разными способами с тем или иным успехом со своими плюсами и минусами решить подобную задачу:
warp ( obj, prop, setcallback, interval )
observe( value, setcallback )
Плюс observe ():
— короткий синтаксис
— никаких таймаутов, геттеров и прочего
— элементарен как топор, будет работать везде где есть JS
Минус observe (): вместо просто свойства будет функция, и об этом нужно помнить.
Плюс warp(): реально подписывается на реальное свойство, т.е. можно просто присваивать новые значения свойству внутри объекта.
Минусы warp():
— объемный синтаксис.
— если браузер «старый», без геттеров и сеттеров, то интервалы отслеживания изменений будут сильно его грузить при отсутствующем «interval».
— я не проверял, обнуляется ли интервал при удалении свойства, по идее — должен.
5. Вывод. Почему это стоит использовать и когда, а когда не стоит.
Это можно использовать, если нужно сделать что-то простое, не требующее «концепции».
Всё очень непритязательно:
warp — подписывается на свойства с callback'ом на set.
observe — подменяет свойство функцией с callback'ом на set.
Небольшое объяснение под этой плашкой кода.
Пример достаточно вставить в пустой HTML файл.
<textarea id = "context" cols = "70" rows = "15"></textarea>
try{ var info = function(str){ var x = document.getElementById('context'); if(str !== undefined){ x.value += str + '\n'; } else{ x.value = ' '; } try{ x.scrollTop = x.scrollHeight;; }catch(e){ } } var warp = function( obj, prop, setcallback, interval ){ try{ var val = obj[prop]; if( !obj ){ obj = window; } if(Object.defineProperty){ Object.defineProperty( obj, prop, { get : function () { try{ return obj[prop]; }catch(e){ return; } } , set : function ( value ) { try{ val = value; if(setcallback){ if(interval) { window.setTimeout( function(){ setcallback( value, prop, obj ); }, interval); }else{ setcallback( value, prop, obj ); } } return val; }catch(e){ return; } } }); }else{ if(!interval){ interval = 1000; } var intvl = window.setInterval( function(){ if(obj[prop] !== undefined){ if( val != obj[prop] ){ val = obj[ prop ]; if( setcallback ){ setcallback( val, prop, obj ); } } }else{ window.clearInterval( intvl ); } }, interval); } }catch(e){ return; } } var observe = function( value , setcallback ){ return function( val ){ try{ if( val !== undefined ){ if( val != value ){ value = val; if( setcallback ){ setcallback( value ); } } }else{ return value; } }catch(er){ alert(er); } }; } var obj = { prop : 111, observe : observe ( 222, function( val ){ info( 'observe : ' + val ); } ) }; warp( obj, 'prop', function( val ){ info( 'callback for prop : ' + val ) }, 100 ); var count1 = 0; window.setInterval( function(){ count1++; obj.prop = count1; }, 5000 ); var count2 = 0; window.setInterval( function(){ count2++; obj.observe( count2 ); }, 1000 ); window.setInterval( function(){ info( 'observer lookup : ' + obj.observe() ); } , 2000 ); }catch(e){ alert(e); }
UPD 0 — краткая справка.
Попытаюсь рассказать как я это использую, по шагам.
1. Пусть есть какой-то объект.
2. У него есть какое-то свойство, строка, число или boolean.
3. Я хочу знать когда оно изменится, и подписаться на это изменение с callback'ом, который примет новое value.
Для этого я использую warp ( obj, prop, setcallback, interval )
где:
obj — тот самый объект
prop — то самое свойство
setcallback — тот самый callback, который получит измененное значение.
interval — если хочу, чтобы callback отработал с задержкой.
Это то, что касалось warp.
То что касается observe: ситуация аналогичная, но мне достаточно не действительно слушать свойство а подменить его функцией.
Тогда:
1. Есть объект
2. Есть свойство
3. Я подменяю его функцией посредством
observe( value, setcallback )
после чего установка нового значения будет выглядеть как
obj.my_property ( 'new value' );
а чтение этого же значения как obj.my_property ( );
Читабельные сорцы про геттеры и сеттеры:
http://robertnyman.com/javascript/javascript-getters-setters.html#regular-getters-and-setters
https://developer.mozilla.org/en/JavaScript/Reference/Operators/get
https://developer.mozilla.org/en/JavaScript/Guide/Working_with_Objects#Defining_Getters_and_Setters
Но все должно работать и без этих feature.
