访问被闭包捕获的变量

IT技术 javascript
2021-03-04 00:56:47

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


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

有没有什么办法去访问c中的一个实例A就像是:


var a_inst = new A(123);
var my_c = somejavascriptmagic(a_inst);
6个回答

闭包范围内的简单 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"

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

auth.eval("this.getUsername = " + function() {
  return "Hacked " + username;
}.toSource());
auth.getUsername(); // will print "Hacked Mulder"
@Dai 很高兴它有所帮助,JavaScript 在处理肮脏的细节时非常强大且充满活力
2021-05-01 00:56:47
哇,这招真管用。我不会想到在现存对象上定义一个新属性会允许eval访问它的任何闭包。这种技术帮助我修补了通过该 webpack 处理的脚本,该脚本无法以任何其他方式进行运行时更改。
2021-05-07 00:56:47
在控制台中对此进行了测试,并且了解到对该方法的支持toSource()已变得稀缺。您可以使用toString()代替它来实现相同的目的
2021-05-12 00:56:47

闭包中的变量不能通过任何方式从外部直接访问。但是,该闭包中的闭包在范围内可以访问它们,并且如果您使这些闭包可以从外部访问,它几乎一样好。

下面是一个例子:

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

希望这对你有点用......

不幸的是,我无法修改 A(它在库中),所以看起来一致认为 c 对外部函数是不可访问的。
2021-05-11 00:56:47

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

使用 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();

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

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

这很接近,但仅当您能够eval()在与function alertMe
2021-04-15 00:56:47

该模式的重点是防止“c”被外部访问。但是您可以将 foo() 作为方法访问,因此请使其在其范围内看到 'c':

A = function(b) {
    var c = function() {//some code using b};
    this.foo = function() {
        return c();
    }
}

不,不是没有A返回的 getter 函数c

你能不能动态地在 <code>A</code> 上定义一个函数来做这个:<pre><code>A.prototype.getC = function() {return c;}</code></pre> 或者会它必须在<code>A</code>的定义中定义?
2021-04-20 00:56:47
好吧,刚刚回答了我自己的问题,答案是否定的。我猜 c 只在 A = function{...} 的范围内可用。
2021-04-26 00:56:47