Отражение Javascript
Есть ли способ получить все методы (частные, привилегированные или общедоступные) из объекта javascript изнутри? Здесь образец объекта:
var Test = function() {
// private methods
function testOne() {}
function testTwo() {}
function testThree() {}
// public methods
function getMethods() {
for (i in this) {
alert(i); // shows getMethods, but not private methods
}
}
return { getMethods : getMethods }
}();
// should return ['testOne', 'testTwo', 'testThree', 'getMethods']
Test.getMethods();
Текущей проблемой является код в getMethods()
, упрощенный пример возвращает только общедоступные методы, но не частные.
изменить: мой тестовый код может (или не обязательно) превышать то, что я надеюсь получить. учитывая следующее:
function myFunction() {
var test1 = 1;
var test2 = 2;
var test3 = 3;
}
существует способ узнать, какие переменные существуют в myFunction()
из myFunction()
. псевдокод будет выглядеть так:
function myFunction() {
var test1 = 1;
var test2 = 2;
var test3 = 3;
alert(current.properties); // would be nice to get ['test1', 'test2', 'test3']
}
Ответы
Ответ 1
Техническая причина, по которой эти методы скрыты, двойственна.
Во-первых, когда вы выполняете метод в тестовом объекте, "this" будет нетипизированным объектом, возвращаемым в конце анонимной функции, которая содержит общедоступные методы в Module Pattern.
Во-вторых, методы testOne, testTwo и testThree не привязаны к определенному объекту и существуют только в контексте анонимной функции. Вы можете прикрепить методы к внутреннему объекту, а затем разоблачить их с помощью общедоступного метода, но это будет не так чисто, как исходный шаблон, и это не поможет, если вы получаете этот код от третьего лица.
Результат будет выглядеть примерно так:
var Test = function() {
var private = {
testOne : function () {},
testTwo : function () {},
testThree : function () {}
};
function getMethods() {
for (i in this) {
alert(i); // shows getMethods, but not private methods
}
for (i in private) {
alert(i); // private methods
}
}
return { getMethods : getMethods }
}();
// will return ['getMethods', 'testOne', 'testTwo', 'testThree']
Test.getMethods();
изменить
К сожалению, нет. Набор локальных переменных недоступен с помощью одного ключевого слова auto.
Если вы удалите ключевое слово "var", они будут привязаны к глобальному контексту (обычно к объекту окна), но единственное, что я знаю об этом, похоже на то, что вы описываете. Было бы много других свойств и методов на этом объекте, если бы вы это сделали.
Ответ 2
Из http://netjs.codeplex.com/SourceControl/changeset/view/91169#1773642
//Reflection
~function (extern) {
var Reflection = this.Reflection = (function () { return Reflection; });
Reflection.prototype = Reflection;
Reflection.constructor = Reflection;
Reflection.getArguments = function (func) {
var symbols = func.toString(),
start, end, register;
start = symbols.indexOf('function');
if (start !== 0 && start !== 1) return undefined;
start = symbols.indexOf('(', start);
end = symbols.indexOf(')', start);
var args = [];
symbols.substr(start + 1, end - start - 1).split(',').forEach(function (argument) {
args.push(argument);
});
return args;
};
extern.Reflection = extern.reflection = Reflection;
Function.prototype.getArguments = function () { return Reflection.getArguments(this); }
Function.prototype.getExpectedReturnType = function () { /*ToDo*/ }
} (this);
Ответ 3
Javascript действительно не имеет понятия частного ничего. Из-за этого, javascript не имеет API отражения как такового. Техника, которую вы используете, не делает их частными, поскольку делает их недоступными; они скрыты, а не частные. Я думаю, вы могли бы что-то сделать, поставив эти методы где-то вручную.
Ответ 4
Часть проблемы с вашим тестовым кодом заключается в том, что Test - это объект, созданный вашим оператором return: "{ getMethods : getMethods }
" У него нет методов testOne, testTwo или testThree; вместо этого они доступны только в том же пространстве имен, что и исходная функция getMethods.
Ответ 5
вы можете использовать трюк var that = this;
:
var Test = function() {
var that = this;
function testOne() {}
function testTwo() {}
function testThree() {}
function getMethods() {
for (i in that) {
alert(i);
}
}
return { getMethods : getMethods }
}();
Ответ 6
С небольшим изменением способа определения функции вы можете достичь того, чего хотите. Оберните фактическую реализацию функции в литературе объекта, она будет выглядеть следующим образом:
(function() {
var obj = {
// private methods
testOne: function () {},
testTwo : function () {},
testThree: function () {},
// public methods
getMethods : function () {
for (i in this) {
alert(i); // shows getMethods, but not private methods
}
}
};
return { getMethods : function(){return obj.getMethods();} }
})();
Ответ 7
Если вы вызываете getMethods() как это, не статично? Конечно, вам нужно будет правильно запустить класс для this
для работы, как ожидалось?
var t = new Test();
t.getMethods();
Если это не сработает, ознакомьтесь с JS Serializer. Я использовал его некоторое время назад для некоторого отладки, и я думаю, что он работал для частных vars.