Подтвердить что ты не робот

Отражение 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']
}
4b9b3361

Ответ 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.