Определение Setter / Getter для непропаренной локальной переменной: невозможно?

Есть несколько предыдущих вопросов по StackOverflow, в которых спрашивается, как получить доступ к локальным переменным через цепочку областей видимости, например, если вы хотите ссылаться на локальные переменные, используя обозначение скобок и строку, вам понадобится что-то вроде __ local __ ["varName"] . До сих пор я не нашел даже самого хакерского метода для достижения этой цели, и не придумал метод после нескольких часов использования всех известных мне уловок.

Его цель - реализовать геттеры / сеттеры для произвольных переменных без родителей. Object.defineProperties или __ defineGet / Setter __ требуют вызова контекста. Для свойств в глобальном или оконном контексте вы можете достичь цели, имея установщик / получатель для прямых ссылок на объект.

Object.defineProperty(this, "glob", {get: function(){return "direct access"})
console.log(glob); //"direct access"

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

Object.defineProperty(Object.prototype, "define", {
    value: function(name, descriptor){
        Object.defineProperty(this, name, descriptor);
    }
};
define("REALLYglobal", {get: function(){ return "above window context"; }});

И затем он доступен во всех фреймах, созданных позже как глобальный маршрутизатор через указанный геттер / сеттер.Старый __ defineGet / Setter __ также работает в этом контексте без указания того, что его вызывать (хотя не работает в Firefox, а метод выше работает).

Таким образом, в принципе можно определить защиту get / set для любой переменной объекта, включая контекст окна / глобального с прямым вызовом объекта (вам не нужно window.propname , просто имя ). Это проблема, связанная с невозможностью ссылаться на переменные без родительской области видимости, поскольку это единственный тип, который может находиться в доступной области, но не иметь адресуемого контейнера. Конечно, они также наиболее часто используются, так что это не крайний случай. Эта проблема также выходит за рамки текущей реализации прокси в ES6 / Harmony, поскольку это проблема, в частности, из-за невозможности обратиться к контейнеру локального объекта с синтаксисом языка.

Причина, по которой я хочу это сделать, заключается в том, что это единственный барьер, позволяющий перегрузить большинство математических операторов для использования в сложных объектах, таких как массивы и хеши, и получить сложное результирующее значение. Мне нужно иметь возможность подключиться к сеттеру в случаях, когда значение устанавливается для типа объекта, который я настроил для перегрузки. Нет проблем, если объект может быть глобальным или может содержаться в родительском объекте, что, вероятно, я просто выберу. Он по-прежнему полезен с a.myObject , но цель состоит в том, чтобы сделать его максимально прозрачным для использования.

Не только это, но было бы действительно полезно иметь возможность выполнить что-то вроде этого:

var point3d = function(){
    var x, y, z;
    return {
        get: function(){ return [x, y, z]; },
        set: function(vals){ x=vals[0]; y=vals[1]; z=vals[2]; }
    };
};

(Это похоже на деструктуризацию ES6, но имеет более общие приложения для реализации функций, связанных с получением / настройкой, а не только транспортировка сложных ценностей). Даже этот базовый код полностью выйдет из строя:

var x = {myname: "intercept valueOf and :set: to overload math ops!", index: 5};
x++; //x is now NaN if you don't implement a setter somehow

Меня не волнует, насколько хакерским является решение, на данный момент для меня это просто сильное любопытство относительно того, можно ли его реализовать, даже если это потребует нарушения всех существующих передовых практик. . Я разбивал Firefox и Chrome несколько сотен раз, пытаясь добиться этого, делая такие вещи, как переопределение / перехват / изменение Object.prototype.valueOf / toString , Function.prototype Function .prototype.constructor , Function.prototype.call/apply , arguments.callee.caller и т. д. с бесконечными рекурсивными ошибками и прочим при попытках ретроспективно оценивать контексты. Единственное, что мне удалось сделать, - это обернуть все это в eval и динамически построить фрагменты кода, что для меня слишком далеко, чтобы я мог его использовать. Единственный другой удаленно успешный маршрут заключался в использовании с в сочетании с предварительным определением всех локальных переменных в контейнере, но это, очевидно, очень навязчиво помимо проблем с использованием с .

38
задан DJMcMayhem 21 July 2017 в 20:52
поделиться