| Беларусь, рогачёв |
Классы и клипы
Свойства, свои и чужие объекты
Если объект "свой", то есть мы можем ему завести setter -метод, то все достаточно тривиально, и мы это обсуждать не будем.
Допустим, что все обстоит несколько сложнее, а именно: у объекта уже есть поле, которое всеми активно используется, а вам зачем-то очень нужно контролировать его изменение, при этом сам объект "чужой", то есть вы не хотите/не можете изменять его исходный код.
Хорошо было бы иметь функцию, которая позволяет следить за полями в "чужом" объекте. Рассмотрим первый возможный вариант. Напишем функцию watchFunction, которая стирает существующее поле в объекте, сохраняя его значение, создает в объекте вместо него свойство с таким же именем и определяет такие getter и setter, чтобы можно было передать функцию реакции:
function reaction (sender, oldValue, newValue){ //функция реакции
trace ("Object: " + sender + ", old value: "
+ oldValue + ", newValue: " + newValue);
return newValue; //нужно вернуть значение,
//которое будет присвоено свойству
}
circle.myField = 5; //исходная переменная в объекте
//заводим функцию прямо в Object.prototype, чтобы можно было
//вызывать ее для любого объекта.
Object.prototype.watchFunction = function (propName, reaction) {
var tmpValue = this[propName]; //сохраняем значение
delete this[propName]; //удаляем переменную
this["get" + propName] = function () { //определяем getter
return this["field" + propName]; //"field" + propName -
// новое имя переменной
};
this["set"+propName] = function (newValue) {
//определяем setter
this["field" + propName] =
reaction(this, this["field" + propName], newValue);
// вызываем функцию реакции, возвращенное значение устанавливаем
// как новое значение свойства
};
//регистрируем новое свойство
this.addProperty (propName, this["get"+propName], this["set"+propName]);
this["field"+propName] = tmpValue;
// восстанавливаем исходное значение
}
circle.watchFunction ("myField", reaction); //включаем слежение
circle.myField = 6;
circle.myField = 7;Теперь, если вы посмотрите на вывод программы, то увидите вот что:
Object: _level0.circle, old value: 5, newValue: 6 Object: _level0.circle, old value: 6, newValue: 7
Если не свойства, то что?
А если нам почему-то не хочется использовать такой способ?
Есть еще один вариант - во Флэш МХ есть функция watch, которая позволяет следить за переменными объекта.
Ее использование выглядит следующим образом: object.watch (propName, reactionFunction, userData), где propName - это имя свойства, за которым нужно следить (строка), reactionFunction - это функция реакции, определение которой должно выглядеть так:
function reactionFunction (propName, oldVal, newVal, userData) {
//...
return newVal; //здесь возвращается значение,
// которое будет в итоге присвоено переменной
}Обратите внимание, что параметр userData - это дополнительные данные, которые могут быть переданы в функцию.
Пример использования стандартной функции watch:
function reaction (sender, oldValue, newValue) { //функция реакции
trace ("Object: " + sender + ", old value: " +
oldValue + ", newValue: " + newValue);
return newValue; //нужно вернуть значение,
// которое будет присвоено свойству
}
circle = {};
circle.myField = 5; //исходная переменная в объекте
circle.watch ("myField", reaction); //включаем слежение
circle.myField = 6;
circle.myField = 7;Рассмотрим различия в интерфейсе стандартной функции watch и "нашей" функции watchFunction, которую мы рассмотрели в предыдущем примере.
Фактически, их только два:
- во-первых, при использовании стандартной функции watch в callback -метод реакции в качестве первого параметра передается имя поля объекта, за которым производится слежение, а в нашей функции - ссылка на объект.
- во-вторых, в стандартной функции watch есть возможность передать дополнительные данные в функцию реакции через четвертый параметр функции реакции и функции watch. В нашей функции такая возможность не предусмотрена.