Access inner variables in JavaScript - javascript

I am writing a userscript for some site.
I need to access inner variable in a function. For example, in following code i need to access
"private property" b of object c
function a(){
var b;
//assignment to b and other stuff
};
var c=new a();
I CANNOT CHANGE THE SITE'S CODE, I ONLY CAN CHANGE BORWSER EXTENSION SCRIPTISH AND WRITE A USERSCRIPT.
My browser is the latest firefox.
I need to gain access even if i would have to change Scriptish.

You can't access to your inner variable of your function, you should make it global variable to get it from outside.
var b;
function a(){
b=1;
//assignment to b and other stuff
};
var c=new a();
document.write(c.b);
and the output will be 1.

In your code b isn't a private variable, but a local variable. And after execution of var c=new a(); b doesn't exist anymore. Thus, you can't access it.
But if you use closures, everything changes:
function a(){
var b;
//assignment to b and other stuff
this.revealB = function() {
return b;
}
};
var c = new a();
alert(c.revealB());
Here b is still a local variable, but its lifetime is affected by closure, thus it's still alive when we call revealB.

It is quite simple thing to do, and it is great for inheritance applications:
You simply return whatever you want, and maybe return it through methods, later reuse it in other functions and build up on it.
Example follows:
function a(){
var b;
//assignment to b and other stuff
return b;
};
// or
function a(){
var b, result;
//assignment to b and other stuff
returnInitial: function() {
return b;
}
// other stuff with b
return result;
};
Later you can use so called "parasitic inheritance" and initiate this whole function inside other function using all local variables and adding new methods, like so:
var a function() {
var b, result;
//assignment to b and other stuff
returnInitial: function() {
return b;
}
// other stuff with b
return result;
}
var extendedA function() {
var base = new a;
var b = a.returnInitial();
a.addToB = function (c) {
var sum = c + a.returnInitial();
return sum;
}
}
So you can now get
var smt = new extendA();
var c = 12; //some number
var sumBC = extendA.addToB(c);
For all there is to these great practices, I recommend yutube search for doug crockford's lectures on js objects handling.
Note that you need to use new since dynamic object handling which javascript uses can crash your original object if you do not initialize a fresh instance.

Related

How can I prevent Node.js from garbage collecting (GC) a critical variable

The property of a variable is purged in Node.js during garbage collection. However, I don't want this to happen. I have found solutions for it, such as saving a variable to a database or file. However, I don't like that approach. I just need a critical section or critical variable protected from garbage collection.
For instance, with the following code:
function a() {
var b;
}
c = new a();
How can I protect variable c from garbage collection?
After time goes by, c.b or c is deleted... In my case, c.b is deleted...
Please help me... I know my english is very poor, but I need your assistance so much.
One thing to note, in your code b and d are not properties on a. They are local variables to the scope inside of the function a, which are not used, thus get cleaned up.
If you change it to:
function a() {
this.b = 1;
this.d = 2;
}
var c = new a();
console.log(c.b) //1
console.log(c.d) //2
You can then reference c.b and c.d and as long as you have a reference to c, it should not get collected. Also if you have it as var b, d; you cannot reference those from outside of the function.
compare to:
function a() {
var b = 1;
var d = 2;
}
var c = new a();
console.log(c.b) //undefined
console.log(c.d) //undefined
I'm not sure, but you don't specify any scope for variable c. This would get c into the most upper scope and prevent it from getting removed by the garbage collector.
You can define c in current scope:
let c;
function doSomething() {
c = {b: 1, d: 2};
}
doSomething();

Explaining variable scope in JavaScript

This is simple, but I cannot understand why it does not work.
var a = function() {
console.log(c); // "10" is expecting, but it is not defined
};
var b = function() {
var c = 10; // local variable, but it is accessibly for b(), I think
a();
}();
Why is variable c not defined? And how can I resolve this problem without passing c into b() as an argument?
this way:
var c = 0;
var a = function() {
console.log(c); // "10" is expecting, but it is not defined
};
var b = function() {
c = 10; // local variable, but it is accessibly for b(), I think
a();
}();
The question is better viewed from the other side. Why would it be defined? a wouldn't really be so reusable with a comment saying "NOTE: You can only run this function if you have a var c declared in the encompassing function". That's just not very discoverable, and means it's very hard to track how long a certain naming scope is used.
A feature of JavaScript that may do what you desire is "closures". This is when you declare an entire function inside of another; it's very handy for callbacks when you don't feel the second function deserves its own naming and place in the code structure.
What will happen here is that the language will automatically see that it needs c (already declared) inside of the function you're declaring, and so it preserves an internal reference to it, associated with the callbackFunction variable. So, you can still refer to it in there.
var b = function() {
var c = 10; // local variable, but it is accessibly for b(), I think
var callbackFunction = function() {
console.log(c);
};
// optionally, place c in a setTimeout, ajax callback, etc.
callbackFunction();
}();
The function a has a new scope in which c isn't defined. You could define var c = 0; outside of a or pass c as argument to a.
you forgot to add parameter to function a
var a = function(c) {
console.log(c); // "10" is expecting, but it is not defined
};
var b = function() {
var c = 10; // local variable, but it is accessibly for b(), I think
a(c);
}();
function inherits parent scope where it was declared, not where it was called. All functions inherit window scope, so you can just make variable c global.
var a = function() {
console.log(c); // "10" is expecting, but it is not defined
};
var b = function() {
c = 10; // local variable, but it is accessibly for b(), I think
a();
}();

Possible to get b without calling `test`?

I am currently thinking about implementing a virtual machine inside of node.js that wraps up other apps. For that I am going to override some basics but there is one point I am not sure of.
var A = (function() {
var b = 1;
var A = function() {};
A.prototype.test = function() { // Can't touch this
return b;
};
A.prototype.foo = function(callback) {
callback();
};
return A;
})();
// Objective: Get b without touching `test` in any way
Is this possible in any way? By injecting prototypes or using call(), apply(), bind() or similar? Any other sort of reflection?
Without using test? Use a different function:
var A = (function() {
var b = 1;
// ...
A.prototype.foo = function () {
return b;
};
return A;
})();
console.log(new A().foo());
Otherwise, no. The snippet is of a closure and only being able to reach local variables through functions defined in the same scope is how they work.

javascript pass parameter values to same named outer scope variables

var a,b,c;
function abc(a,b,c){
console.log("a is"+ a + ", b is"+ b + ", c is"+ c);
}
a; // undefined
b; // undefined
c; // undefined
I will be passing through strings a,b,c, but would like to also be able to access them once they are passed through the function.
So if I call abc("d","e","f"), I'd like that function to run using those three strings, but afterwards, outside of its own scope, I'd also like to be able to use a="d", b="e", and f="f".
Could someone explain how this is done? I think that even though they are declared outside of the function, the fact that it's the same name is throwing me off.
I remember something in PHP about adding & before the parameter...
Thanks!
I'm not sure what you're asking here, but it works just out of the box like you want it.
Since ECMAscript has function scope, the variables a, b and c will get locally resolved within the function context of abc(). The outer declarations of those
variable names (lets call them free variables), will never get accessed because the lookup process will find those names first within its *own context, resolve them and stop there.
If you just want to set those free variables which are part of a parent context, you probably should rename your formal parameters for convenience and then pass over the values
function abc(some, other, name) {
a = some;
b = other;
c = name;
}
Hopefully that parent scope where a, b and c are declared is not the global scope. That is very correctly still considered bad practice and karma, for a couple of reasons.
Best practice would be to give the inner variables different names, e.g. by prefixing them with 'inner' or the initials of the function name. Not only can you then simply assign the values to the outer variables with a simple a = innerA, but it also makes your code more readable.
You can't use the variables in the outer scope if they're masked by function parameters with the same name.
You could, if they were named properties of a variable that is in the outer scope. In browsers, global variables are actually just properties of the window variable:
var myobj = {};
function abc(a, b, c) {
myobj.a = a;
myobj.b = b;
myobj.c = c;
}
// you can now use those values
Firstly, I think you mean:
var a, b, c;
function abc(_a, _b, _c) {
a = _a;
b = _b;
c = _c;
}
abc(1, 2, 3);
console.log("a is"+ a + ", b is"+ b + ", c is"+ c); // 1, 2, 3
Given that said, I think this approach is not a good practise. Please organise them within a closure or a namespace. For example, here is an acceptable design pattern :
(function(g) {
var _SomeClass = function(a, b, c) {
this.a = a;
this.b = b;
this.c = c;
}
_SomeClass.prototype = {
printValues: function() {
console.log(this.a, this.b, this.c);
},
doSomething: function() {
// do something here
},
_privateMethod: function() {
// should not be called from outside the closure
}
}
g.SomeClass = _SomeClass;
})(window);
var myClass = new SomeClass(1, 2, 3);
myClass.printValues();

Accessing variables trapped by closure

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);
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"
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...
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.
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();
}
}
No, not without a getter function on A which returns c
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.
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
You should be able to use an if statement and do something like:
if(VaraiableBeingPasses === "somethingUniqe") {
return theValueOfC;
}

Categories