Я знаю про 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.