Javascript объект инкапсуляции, которая отслеживает изменения - PullRequest
4 голосов
/ 07 января 2011

Можно ли создать контейнер объектов, в котором можно отслеживать изменения

Указанный объект является сложным вложенным объектом данных. (соответствует JSON).

Обертка позволяет вам получить объект и сохранить изменения, не указав конкретно, что это за изменения

Существует ли шаблон проектирования для этого вида инкапсуляции

Глубокое клонирование не вариант, так как я пытаюсь написать такую ​​обертку, чтобы избежать этого.

Решение сериализации следует рассматривать только при отсутствии других решений.

Примером использования будет

var foo = state.get();
// change state
state.update(); // or state.save();
client.tell(state.recentChange());

Может помочь фрагмент jsfiddle: http://jsfiddle.net/Raynos/kzKEp/

Похоже, реализация внутреннего хэша для отслеживания изменений - лучший вариант.

[редактировать]

Для пояснения это на самом деле делается на файле node.js на сервере. Единственное, что меняется, - это то, что решение может быть специфичным для реализации V8.

Ответы [ 5 ]

2 голосов
/ 07 января 2011

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

Например, представьте, что у вас есть этот объект:

var obj = new WrappedObject({
    property1: {
        property1a: "foo",
        property1b: 20,
    }
})

Если вы не оберните объект, содержащийся в porperty1, вы получите только событие "get" для property1, и только это, потому что когда кто-то запускает obj.property1.property1a = "bar" единственное взаимодействие, которое у вас будетс obj, будет, когда он запрашивает ссылку на объект, содержащийся в property1, и модификация будет происходить в ненаблюдаемом объекте.

Лучший подход, который я могу себе представить, это итерация по всем свойствамВы оборачиваете первый объект и рекурсивно создаете объект-обертку для каждого typeOf(property) == "Object".

Надеюсь, мое понимание вашего вопроса было правильным.Извините если нет!Это мой первый ответ здесь: $.

2 голосов
/ 07 января 2011

Отбрасывая аспект этой проблемы, связанный с javascript, есть только три способа узнать, изменилось ли что-то:

  1. Сохраните копию или представление для сравнения.
  2. Соблюдайтесамо изменение происходит в пути.
  3. Получайте уведомления об изменении.

Теперь верните эти понятия обратно в javascript, и у вас будут следующие шаблоны:

  1. Копировать: либо глубокий клон, либо полная сериализация, либо хеш.
  2. Наблюдать: принудительно использовать установщик или нажать на движок javascript (не очень применимо)
  3. Уведомить:изменение кода, который вносит изменения для публикации событий (опять же, не очень применимо).

Учитывая, что вы исключили глубокий клон и использование сеттеров, я думаю, что ваш единственный вариант - это некоторыеформа сериализации ... см. реализацию хэша здесь .

1 голос
/ 07 января 2011

Вы можете использовать решение, которое использует processing.js .Напишите сценарий, который обычно обращается к обернутому объекту ...

var foo = state.get();
foo.bar = "baz";
state.update();
client.tell(state.recentChange());

... но в браузере (или на сервере, если скорость загрузки важна) перед его запуском проанализируйте код и преобразуйте его вthis,

var foo = state.get();
state.set(foo, "bar", "baz");
state.update();
client.tell(state.recentChange());

Это также может быть использовано для других полезных вещей, таких как перегрузка операторов:

// Before conversion
var a=new Vector(), b=new Vector();
return a + b * 3; 

// After conversion
var a=new Vector(), b=new Vector();
return Vector.add(a,Vector.multiply(b,3));
1 голос
/ 07 января 2011

Есть нечто, называемое реактивное программирование , которое напоминает то, о чем вы спрашиваете, но оно более сложное и, вероятно, будет излишним.

Кажется, вы хотели бы сохранить историюзначения, правильно?Это не должно быть слишком сложно, если вы ограничиваете изменения в функции установки.Конечно, это сложнее в javascript, чем в некоторых других языках.Настоящие частные поля требуют некоторого умного использования замыканий.

Если вы можете сделать все это, просто напишите что-то подобное в сеттер.

function setVal(x)
{
    history.push(value);
    value = x;
}
0 голосов
/ 07 января 2011

Может показаться, что node-proxy реализует способ сделать это, обернув прокси вокруг всего объекта. Я рассмотрю более подробно, как это работает.

https://github.com/samshull/node-proxy

...