Мониторинг всех свойств объекта JavaScript (магические геттеры и сеттеры)

Как мне эмулировать магические методы получения / установки __get () и __set () в стиле PHP в 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 доступна реализация: узел -прокси.


person BMiner    schedule 08.08.2011    source источник
comment
Эта функция, называемая прокси, является частью ECMAScript 6, а не 5.   -  person Raynos    schedule 08.08.2011
comment
Хороший улов. Доработал свой пост. Спасибо!   -  person BMiner    schedule 08.08.2011


Ответы (3)


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

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

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

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

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

person Domenic    schedule 08.08.2011
comment
Хорошо ... Я могу понять взломы на стороне клиента, особенно проблемы совместимости браузера. А как насчет серверной стороны? Например, на Node.JS? Как вы думаете, там можно что-то сделать? - person BMiner; 08.08.2011
comment
Я на самом деле только что отредактировал свой пост с моими находками там, пока вы комментировали :) - person Domenic; 08.08.2011

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

Ой, я только что понял, что вы хотите отслеживать все свойства, а не конкретное свойство ... Вышеупомянутое решение - следить за определенным свойством.

person Juan Mendes    schedule 08.08.2011

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

person PlagueEditor    schedule 08.08.2011
comment
Спасибо за вашу помощь. onpropertychange выглядит так, как будто это только для объектов DOM. Это должно работать для старых необработанных объектов JS. - person BMiner; 08.08.2011