динамические геттеры и сеттеры - возможность

Я пытаюсь решить проблему, которая пришла мне в голову в последнее время. Допустим, мы хотели бы и знали бы, как сделать так, чтобы в javascript были динамические геттеры и сеттеры, больше похожие на те, что в php (__get, __set). Но поскольку javascript не имеет универсального свойства, единственное, что мы могли бы сделать, это предоставить список возможных ключей и выполнить итерацию, чтобы добавить геттеры и сеттеры только для них, и надеяться, что никто другой никогда не появится.

Но проблема далеко не решена. Итак, следующий подход, который пришел мне в голову, заключался в том, чтобы использовать неприятный хак с try и catch, чтобы в любой момент имя не было определено в объекте, чтобы использовать catch в качестве геттера (по крайней мере), а затем возобновить код, жестко и, возможно, бессмысленное дело. Но отсюда и возникла моя вторая проблема в таком использовании:

console.log(g.someundefinedproperty); 

результатом был бы вызов console.log, показывающий undefined без каких-либо исключений. И тогда меня осенило: что, если бы я использовал оригинальный window.undefined геттер и сеттер, в конце концов, он должен вызываться каждый раз, когда я ошибаюсь и неправильно пишу слово или что-то в этом роде.

Так что я попробовал

Object.defineProperty(window, 'undefined', {
    get : function ()
    {
         // functional code, including getting the caller and figuring out
         // where we are, and what we have to do... easy :D

         console.log('works');
    },
    set : function ()
    {
         // some couple more fine hacks here
         console.log('this too');
    }
});

Но, к сожалению, свойство окна undefined равно configurable : false. Другие попытки взлома заключались в клонировании объекта window, за исключением undefined и внутреннего свойства window. И на новом объекте, чтобы определить новый undefined (обратите внимание на иронию), а затем window = mybetterwindow;

Поскольку это не вызвало каких-либо проблем, я возлагал большие надежды, но система снова подвела меня, поскольку window не может быть перезаписана по замыслу. Я предположил, что у него есть собственный геттер и он восстанавливается на основе прототипа, найденного в window.prototype или даже лучше Window.prototype (обратите внимание на верхний регистр).

В качестве последнего шага в этом эксперименте я переопределил undefined при запуске этого прототипа. Безрезультатно, ничего не изменилось ... Я попытался создать new Window(), но Window не конструктор, не получилось!

Поскольку у меня кончились идеи, я пишу здесь эту мольбу о помощи. Если у вас есть идеи, как решить проблему динамических геттеров и сеттеров (the existencial problem of life, universe and everything else) таким способом, который никоим образом не изменяет ... способ, которым я использую объекты (и в качестве бонуса это не need to break a hole в fabric of time and space) или синтаксис, умоляю вас говорить или вечно молчать :).


person helly0d    schedule 12.12.2012    source источник
comment
У вас есть реальная жизненная проблема, которую вы пытаетесь решить?   -  person Ash Burlaczenko    schedule 13.12.2012
comment
Я думаю, что переосмысление undefined действительно рискует пробить дыру в ткани времени и пространства. Может поэтому в ES5 это запрещено. Это интересный вопрос, однако я предвижу, что в большинстве ответов и комментариев будет сказано, что универсальные средства доступа не нужны и вредны. Черт возьми, вы даже приводите в пример PHP! :П   -  person bfavaretto    schedule 13.12.2012
comment
Конечно, знаю, не будь здесь смысла, если бы у меня не было. Это дизайн, которому я должен следовать при разработке фреймворка, над которым я работаю.   -  person helly0d    schedule 13.12.2012
comment
@bfavaretto Что ж, PHP - прекрасный пример того, что можно сделать, и он мне действительно нужен сейчас.   -  person helly0d    schedule 13.12.2012
comment
@ helly0d Это была просто шутка! Как я уже сказал, меня интересует поднятый вами вопрос.   -  person bfavaretto    schedule 13.12.2012
comment
@bfavaretto Что ж, мы можем начать полную дискуссию о том, почему вы должны уметь это делать и какую силу это может дать :). Но проблема все еще не решена, надеюсь, кто-нибудь сможет на нее ответить. И бог его знает, я все перепробовал.   -  person helly0d    schedule 13.12.2012
comment
Единственный способ сделать то, что вы хотите, - использовать прокси ECMAScript 6, они могут использоваться на современных движках (IIRC, они доступны в FF4 + и Chrome 19+). См. Также: stackoverflow.com/questions/2266789/   -  person Christian C. Salvadó    schedule 13.12.2012
comment
@ helly0d Да, бог знает, что ты пробовал: D. Меня тоже очень интересует этот вопрос.   -  person khael    schedule 13.12.2012
comment
К вашему сведению, мне стало любопытно, я немного поиграл и написал короткую запись в блоге, которую вы можете найти полезной или интересной. И я почти уверен, что в отличие от поспешного и туманного ответа, который я сформулировал ранее, он действительно затрагивает ваш вопрос! blog.svidgen.com/2012/12/getters-setters- and-redefining.html   -  person svidgen    schedule 17.12.2012
comment
@svidgen Интересно для тех, кто не будет использовать этот код, потому что в широком приложении мне пришлось бы обернуть все приложение функцией, которую нужно переписать, а затем evaled, до которой я теряю время и память. У меня есть друг (@khael), который выполняет какую-то «Monkey Patching», используя ту же технику, но на PHP, и делает это только один раз для каждого проекта, после чего сохраняет проект как «Monkey Patched».   -  person helly0d    schedule 18.12.2012
comment
Когда вы полагаетесь на геттеры и сеттеры или язык сценариев в этом отношении, вы уже решили пожертвовать обоими. По крайней мере, в этом случае или при аналогичной предварительной обработке сервера вы получаете большой удар только во время загрузки, как вы уже делаете со скриптовыми языками.   -  person svidgen    schedule 18.12.2012
comment
@svidgen В этом суть сеттеров и геттеров. У меня уже есть данные, загруженные где-то в памяти, но я хочу получить их или установить их только тогда, когда это необходимо, поэтому у меня есть это преимущество, заключающееся в выполнении сортировки и некоторых других вещей только тогда, когда я прошу об этом, но с вашим self writing аксессуаром это боль в a ** для браузера, чтобы все приложение было переписано и переинтерпретировано, и отладка также была бы болезненной, но спасибо за идею.   -  person helly0d    schedule 18.12.2012
comment
Это не такой большой успех, как вы можете себе представить. И отладка будет похожа на то, что вы бы испытали при использовании замыканий. Но я не буду настаивать, если вы уверены, что это неработоспособно. Это была просто мысль. И единственное полностью кроссбраузерное решение, которое я могу придумать.   -  person svidgen    schedule 18.12.2012
comment
Я бы поспешил возразить против этого из-за сложности, с которой вы столкнулись бы с этой переписыванием в состоянии высокой функциональности. Но если бы можно было потратить на это немного времени, я бы не стал слишком беспокоиться об эффективности большинства приложений.   -  person svidgen    schedule 18.12.2012


Ответы (2)


Но, к сожалению, неопределенное свойство окна configurable: false

Это верно только начиная с EcmaScript 5.1. Раньше его можно было перезаписывать.

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

Нет, не сработало бы. Существует разница между undefined значением и глобальной переменной. "неопределенный". Переменная не оценивается каждый раз, когда встречается значение undefined (например, в typeof (void 0)), только когда вы используете его явно (например, в g.someprop === undefined).

Есть идеи, как решить проблему динамических геттеров и сеттеров?

Есть только одно решение: Proxies. К сожалению, это всего лишь проект гармонии, и в настоящее время в Firefox Javascript 1.8 поддерживается только . 5.

См. Также Есть ли эквивалент функции __noSuchMethod__ для свойств или способ реализовать ее в JS?, Обнаруживать появление нового свойства добавляется к объекту Javascript? или Как определить, когда свойство добавлено к объекту JavaScript?, который реализует решение для опроса (проверка изменений через setInterval).

Для чистого решения в настоящее время необходимо использовать явную функцию получения, которой вы передаете имя свойства (g.get("someundefinedproperty")).

person Bergi    schedule 12.12.2012

То, что вы пытаетесь выполнить (глобальный получатель для любого неопределенного свойства), выходит за рамки кроссбраузерного JavaScript.

Ближайшая функциональность заключается в использовании __defineGetter__ для добавления определенного свойства ко всем объектам:

var o = Object.prototype;
o.__defineGetter__("testo", function() { return "yo in testo"; });
alert({}.testo);
alert((new Date()).testo);

http://jsfiddle.net/NLCvs/2/

Это может быть полезно, если вы можете заранее предсказать имя потенциально неопределенных свойств. Даже в этом случае было бы довольно хакерским и плохим тоном добавлять метод доступа ко всем объектам для свойства, которое может быть неопределенным.

Лучшим вариантом является рефакторинг кода, когда можно получить доступ к неопределенному свойству:

function getter(o, n) {
 return typeof o[n] == 'undefined' ? 'some default value' : o[n];
}
var obj = { hello: 'world' };
alert(getter(obj, 'hello'));
alert(getter(obj, 'an_undefined_property'));

Еще лучший вариант - использовать миксин для установки любых свойств по умолчанию, к которым вам потребуется доступ, например, через jQuery.extend

var defaults = {
 required: 'this property is required'
};
var my_object = {
 something_else: 'this is something else'
};
var o = jQuery.extend({}, defaults, my_object);

// o.required === 'this property is required'
// o.something_else === 'this is something else'
person leepowers    schedule 12.12.2012