Reputation: 1894
I was wondering if there is any way to access variables trapped by closure in a function from outside the function; e.g. if I have:
A = function(b) {
var c = function() {//some code using b};
foo: function() {
//do things with c;
}
}
is there any way to get access to c
in an instance of A
. Something like:
var a_inst = new A(123);
var my_c = somejavascriptmagic(a_inst);
Upvotes: 55
Views: 40639
Reputation: 197
I massively improved the code of @Arch . It uses chrome debugger and requires an extension.
class HiddenClass {
hiddenProperty;
constructor(value) {
this.hiddenProperty = value;
}
}
var Secret = (() => {
let _secret;
return function Secret(secret) {
_secret = secret;
}
})();
let obj = new Secret(new HiddenClass(1337));
console.log(await scopeInspect(obj, ["hiddenProperty"]));
// HiddenClass {hiddenProperty: 1337}
https://github.com/eyalk11/scopeinspect-js
Upvotes: 0
Reputation: 61
To those seeking an actual answer, I've created this.
https://github.com/ArhanChaudhary/scopeinspect-js
Unfortunately, it requires installing a Chrome extension for usage meaning you can't use this in actual code. The purpose of this project is to demonstrate that inspecting internal JavaScript state is possible under specific conditions.
Upvotes: 0
Reputation: 1
You should be able to use an if statement and do something like:
if(VaraiableBeingPasses === "somethingUniqe") {
return theValueOfC;
}
Upvotes: -5
Reputation: 20817
If none of the above is possible in your script, a very hacky solution is to store it in a hidden html-object:
// store inside of closure
html.innerHTML+='<div id="hiddenStore" style="display:none"></div>';
o=document.getElementById("hiddenStore")
o.innerHTML="store this in closure"
and outside you can read it with
document.getElementById("hiddenStore").innerHTML
Upvotes: 0
Reputation:
If you only need access to certain variables and you can change the core code there's one easy answer that won't slowdown your code or reasons you made it a closure in any significant way. You just make a reference in the global scope to it basically.
(function($){
let myClosedOffObj = {
"you can't get me":"haha getting me would be useful but you can't cuz someone designed this wrong"
};
window.myClosedOffObj = myClosedOffObj;
})(jQuery);
myClosedOffObj["you can't get me"] = "Got you now sucker";
Proof of concept: https://jsfiddle.net/05dxjugo/
This will work with functions or "methods" too.
Upvotes: 2
Reputation: 101
Answers above are correct, but they also imply that you'll have to modify the function to see those closed variables.
Redefining the function with the getter methods will do the task. You can do it dynamically. See the example below
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();
now you can access message by calling b.getMesage()
Of course you'll have to deal with multiple calls to alertMe, but its just a simple piece of code proving that you can do it.
Upvotes: 10
Reputation: 4893
A simple eval inside the closure scope can still access all the variables:
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"
But you cannot directly overwrite a method, which is accessing closure scope (like getUsername()), you need a simple eval-trick also:
auth.eval("this.getUsername = " + function() {
return "Hacked " + username;
}.toSource());
auth.getUsername(); // will print "Hacked Mulder"
Upvotes: 27
Reputation: 1021
Variables within a closure aren't directly accessible from the outside by any means. However, closures within that closure that have the variable in scope can access them, and if you make those closures accessible from the outside, it's almost as good.
Here's an example:
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
Hopefully that's slightly useful to you...
Upvotes: 22
Reputation: 4132
The whole point to that pattern is to prevent 'c' from being accessed externally. But you can access foo() as a method, so make it that it will see 'c' in its scope:
A = function(b) {
var c = function() {//some code using b};
this.foo = function() {
return c();
}
}
Upvotes: 4