Отслеживать все свойства объекта JavaScript (магические методы получения и установки) - PullRequest
26 голосов
/ 08 августа 2011

Как мне эмулировать магический метод получения / установки в PHP в стиле __get () и __set () в JavaScript? Многие люди говорят, что это в настоящее время невозможно. Я почти уверен, что это возможно, потому что проекты, подобные nowjs (http://nowjs.com), делают что-то подобное.

Я знаю, что вы можете использовать get и set , но они не работают, если вы не уверены, каким будет имя свойства. Например, что если вы хотите, чтобы обработчик событий выполнялся при создании нового свойства ?

Пример того, что я хотел бы сделать:

var obj = {};
notify(obj, function(key, value) {
   //key is now the name of the property being set.
   //value is the value of the property about to be set
   console.log("setting " + key + " to " + value);
});
obj.foo = 2; //prints "setting foo to 2"
obj.bar = {a: 2}; //prints "setting bar to [Object]"
//Notice that notify() worked even though 'foo' and 'bar' weren't even defined yet!

(Вопрос похож на следующие вопросы:

)

РЕДАКТИРОВАТЬ: Похоже, эта функция называется "динамические прокси" и должна появиться в стандарте ECMAScript "Harmony" (вероятно, ES6). Вы можете прочитать больше здесь . Новый объект «Прокси» вводится с помощью нескольких методов (т. Е. Create () и createFunction ()).

Можно сделать это:

//Constructing an object proxy (proto is optional)
var proxy = Proxy.create(handler, proto);
proxy.foo = 2; //Triggers 'set' function in the handler (read about it)

Итог здесь: он не работает в большинстве браузеров, но для Node.js доступна реализация: node-proxy .

Ответы [ 3 ]

13 голосов
/ 08 августа 2011

Просматривая исходный код nowjs, я полагаю, что они делают это, постоянно отслеживая объект now и передавая изменения между клиентом и сервером при каждом их обнаружении.Однако я признаю, что еще не полностью прогнал их код.

В браузере это можно сделать с помощью забавных setInterval хаков.

РЕДАКТИРОВАТЬ :да, это действительно то, что они делают: строка 368 клиента now.js.Они делают еще несколько хитростей , чтобы при обнаружении нового свойства в будущем доступ к нему перехватывался геттерами и сеттерами, но эти изменения выполняются только каждые 1000 мс в setTimeout.

Еще одним доказательством того, что это невозможно в текущем JavaScript, является то, что предложение прокси-серверов для ECMAScript Harmony специально разработано для включения таких сценариев, что очень сильно подразумевает, что они не могут быть выполнены в настоящее время.Последние браузеры Mozilla имеют прототип реализации прокси , если, возможно, этого достаточно.И, очевидно, V8 работает над добавлением поддержки , чего может быть достаточно в зависимости от того, какая версия V8 Node используется в эти дни.

EDIT2 : о, круто, на сервер сторона, очевидно, теперь использует прокси!Что, вероятно, означает, что они достаточно зрелые в Node для вашего использования.Посмотрите, что они делают на https://github.com/Flotype/now/blob/master/lib/proxy.js. Или просто сделайте var Proxy = require("nodejs-proxy") и надеюсь, что они следуют спецификации, чтобы вы могли воспользоваться документацией из MDC и других источников.

2 голосов
/ 08 августа 2011

В Firefox вы можете использовать Object.watch .Если вы посмотрите на эту тему, Object.watch () для всех браузеров? , есть пример использования чего-то похожего во всех браузерах.

Ой, я просто понял, что вы хотитесмотреть все свойства, а не конкретное свойство ... Решение, приведенное выше, заключается в просмотре определенного свойства.

0 голосов
/ 08 августа 2011

Возможно этот пост поможет ...? Это, однако, только для определенных свойств и браузеров, основанных на Gecko ... Если вам нужна поддержка других браузеров, он глючит, но вы можете посмотреть на onpropertychange. Вот страница MSDN . Надеюсь, это поможет немного ...

...