访问由闭包捕获的变量

Kie*_*old 38 javascript

我想知道是否有任何方法可以从函数外部访问函数中闭包所捕获的变量; 例如,如果我有:


A = function(b) {
    var c = function() {//some code using b};
    foo: function() {
        //do things with c;
    }
}
Run Code Online (Sandbox Code Playgroud)

有没有办法c在一个实例中访问A.就像是:


var a_inst = new A(123);
var my_c = somejavascriptmagic(a_inst);
Run Code Online (Sandbox Code Playgroud)

lam*_*345 16

闭包范围内的简单eval仍然可以访问所有变量:

function Auth(username)
{
  var password = "trustno1";
  this.getUsername = function() { return username }
  this.eval = function(name) { return eval(name) }
}

auth = new Auth("Mulder")
auth.eval("username") // will print "Mulder"
auth.eval("password") // will print "trustno1"
Run Code Online (Sandbox Code Playgroud)

但是你不能直接覆盖一个访问闭包范围的方法(比如getUsername()),你还需要一个简单的eval-trick:

auth.eval("this.getUsername = " + function() {
  return "Hacked " + username;
}.toSource());
auth.getUsername(); // will print "Hacked Mulder"
Run Code Online (Sandbox Code Playgroud)

  • 在控制台中对此进行了测试,并了解到对“toSource()”方法的支持已经变得稀缺。您可以使用“toString()”代替它来实现相同的效果。 (2认同)

psm*_*may 15

封闭内的变量无法通过任何方式直接从外部访问.但是,具有变量范围的闭包内的闭包可以访问它们,如果从外部访问这些闭包,它几乎同样好.

这是一个例子:

var A = function(b) {
    var c = b + 100;
    this.access_c = function(value) {
        // Function sets c if value is provided, but only returns c if no value
        // is provided
        if(arguments.length > 0)
            c = value;
        return c;
    };
    this.twain = function() {
        return 2 * c;
    };
};
var a_inst = new A(123);
var my_c = a_inst.access_c();
// my_c now contains 223
var my_2c = a_inst.twain();
// my_2c contains 446
a_inst.access_c(5);
// c in closure is now equal to 5
var newer_2c = a_inst.twain();
// newer_2c contains 10
Run Code Online (Sandbox Code Playgroud)

希望这对你有点帮助......

  • 不幸的是,我无法修改A(它在库中)所以看起来共识是外部函数无法访问c. (6认同)

小智 8

上面的答案是正确的,但它们也暗示你必须修改函数才能看到那些已关闭的变量.

使用getter方法重新定义函数将完成任务.你可以动态地做到这一点.请参阅下面的示例

function alertMe() {
    var message = "Hello world"; 
    console.log(message);
}

//adding the getter for 'message'
var newFun = newFun.substring(0, newFun.lastIndexOf("}")) + ";" + "this.getMessage = function () {return message;};" + "}";

//redefining alertMe
eval(newFun);

var b = new alertMe();
Run Code Online (Sandbox Code Playgroud)

现在您可以通过调用b.getMesage()来访问消息

当然,你必须处理多次调用alertMe,但它只是一段简单的代码证明你可以做到.