Отражение JavaScript - PullRequest
       27

Отражение JavaScript

28 голосов
/ 09 ноября 2008

Есть ли способ получить все методы (приватные, привилегированные или публичные) объекта 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(), упрощенный пример вернет только открытые методы, но не частные.

edit : мой тестовый код может (или не может) усложнять то, что я надеюсь получить. учитывая следующее:

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']
}

Ответы [ 7 ]

28 голосов
/ 09 ноября 2008

Техническая причина, по которой эти методы скрыты, двояка.

Во-первых, когда вы выполняете метод для объекта Test, «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();

редактирование:

К сожалению, нет. Набор локальных переменных недоступен через одно автоматическое ключевое слово.

Если вы удалите ключевое слово «var», они будут присоединены к глобальному контексту (обычно объекту окна), но это единственное, что мне известно о поведении, похожее на то, что вы описываете. Если бы вы сделали это, у этого объекта было бы много других свойств и методов.

5 голосов
/ 10 мая 2012

С 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);
2 голосов
/ 09 ноября 2008

Javascript не имеет ничего общего с частным. Из-за этого у javascript нет API отражения как такового. Техника, которую вы используете, не столько делает их приватными, сколько делает их недоступными; они скрытые, а не частные. Я думаю, что вы могли бы чем-то управлять, поместив эти методы куда-нибудь вручную.

1 голос
/ 16 апреля 2012

С небольшим изменением способа определения функции вы можете достичь того, чего хотите. Оберните фактическую реализацию функции в литерал объекта, после чего она будет выглядеть так:

(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();} }
})();
1 голос
/ 25 ноября 2008

вы можете использовать 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 }
}();
1 голос
/ 09 ноября 2008

Часть проблемы с вашим тестовым кодом заключается в том, что Test - это объект, созданный вашим оператором return: "{ getMethods : getMethods }" У него нет методов testOne, testTwo или testThree; вместо этого они доступны только в том же пространстве имен, что и исходная функция getMethods.

0 голосов
/ 09 ноября 2008

Если вы вызываете getMethods () таким образом, разве это не статично? Конечно, вам нужно правильно инициализировать класс для this, чтобы он работал как положено?

var t = new Test();
t.getMethods();

Если это не сработает, посмотрите на JS Serializer . Я использовал это некоторое время назад для некоторой отладки, и я думаю, что это работало для приватных переменных.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...