29

有没有办法从内部获取 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']
}
4

7 回答 7

29

隐藏这些方法的技术原因是双重的。

首先,当您在 Test 对象上执行方法时,“this”将是在包含模块模式的公共方法的匿名函数末尾返回的无类型对象。

其次,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”关键字,它们将附加到全局上下文(通常是窗口对象),但这是我所知道的唯一与您所描述的行为相似的行为。但是,如果您这样做,该对象上会有很多其他属性和方法。

于 2008-11-09T00:59:51.320 回答
5

来自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);
于 2012-05-10T16:07:05.993 回答
2

Javascript 并没有真正的私有概念。因此,javascript 本身没有反射 API。您使用的技术并没有使它们变得私有,而是使它们无法访问;它们是隐藏的,不是私人的。我认为您可以通过手动将这些方法放在某处来管理某些事情。

于 2008-11-08T23:35:54.123 回答
1

您的测试代码的部分问题在于 Test 是您的 return 语句创建的对象:“ { getMethods : getMethods }”它没有 testOne、testTwo 或 testThree 方法;相反,它们仅在与原始 getMethods 函数相同的命名空间中可用。

于 2008-11-08T23:58:06.123 回答
1

你可以使用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 }
}();
于 2008-11-24T21:54:06.733 回答
1

对函数的定义方式稍作改变,您就可以实现您想要的。将函数的实际实现包装在一个对象字面量中,它看起来像这样:

(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();} }
})();
于 2012-04-16T12:56:59.337 回答
0

如果你这样调用 getMethods() ,它不是静态的吗?当然,您需要正确初始化课程this才能按预期工作?

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

如果这不起作用,请查看JS Serializer。我前一段时间用它进行了一些调试,我认为它适用于私有变量。

于 2008-11-08T23:21:57.303 回答