If anonymous JavaScript functions can access all variables, what about regular functions? - javascript

In Javascript function variables are local unless they're not declared with "var". That is, unless those functions are anonymous (like the ones used in setInterval and setTimeout. In that case, they have global access to all available variables within the scope that called the anonymous functions.
What about regular functions then? Is there any way to allow them to access all variables too? I ask this due to some cases of having very complicated functions under 1 parent function with many variables, where I suddenly have to turn them from anonymous into regular functions.
For example, let's assume my original anonymous function called alert and now I want to do it through a regular function:
myFunction()
function myFunction() {
var a='b' //,b=...,c=...,d=...,e=...,f=...,g=...,h=...,i=...,j=...,k=...
setInterval(function(){ alert(a) }, 3000) // Works even though a is local
setInterval(function(){ dummy() }, 3000) // Fails, but would work if I used dummy(a).
// But then I'd have to use dummy(a,b,c,d,e,f,g,h,i,j,k,...)
}
function dummy() { // It would have worked had I used dummy(a)
alert(a)
}

The question is not about anonymous functions. Take this two lines:
setInterval(function named (){ alert(a) }, 3000);
setInterval(function(){ alert(a) }, 3000);
both work although one is named, and one is not. The real problem here is scoping, a is not visible to dummy because dummy gets declared outside of a's scope:
{ // brackets start a scope
let a = "b"; // a gets declared in this scope
//...
} // scope ends
function dummy() { /*..*/ } // outside of scope
To solve this, move dummy into a's scope:
function myFunction() { // start of scope
let a = "b";
setInterval(function(){ dummy() }, 3000);
function dummy() {
alert(a); // a can be accessed as it is inside of the scope
}
} // end of scope
(I used let instead of var because it has stricter, and therefore easier to justify, scoping rules)

Related

send variable to another if statement

I'm struggling with variables, why is this one not defined?
function myFunction(){
if(){
let mytimer = setInterval(function() {
alert("hello");
}, 1000);
}
else if(){}
else{
clearTimeout(mytimer); <--- this is not set
}
if(){
clearTimeout(mytimer); <--- this one is not set aswell.
}
}
I also have it in another if statement a bit under in the same function, it's not set aswell. What am I missing? I had var mytimer first but then I remember let should exist outside the statement right?
Edit: I am unable to put the variable outside my if statement
This is an issue with scope.
Your variable, mytimer, is being declared locally within your if statement, meaning it can't be accessed by anything outside of that if statement as it doesn't exist there.
You could declare it outside the if blocks to start with and then reference it inside them when needed like so:
function myFunction(){
//Declare mytimer here
let mytimer = 0;
if(//condition){
mytimer = setInterval(function() {
alert("hello");
}, 1000);
} else if(//another condition){
//do something
} else{
clearTimeout(mytimer); <--- this will now be accessible here
}
if(){
clearTimeout(mytimer); <--- as will this one
}
}
Edit: I see from your edit you've said you can't declare your variable outside your if blocks.
As far as I'm aware, it's not possible to access local variables outside of scope in JavaScript; therefore, your only option is most likely to rewrite the program in a way that means you can unfortunately.
when you define a variable inside of a block scope like if, it is not accessible from outside of the scope, you can change the scope, write your variable outside of block scope or, you can use var instead of let ...
function myFunction(){
let myTimer= null
if(){
myTimer = setInterval(function() {
alert("hello");
}, 1000);
}
}
Universal answer:
The way you asked the question, your variable/s should be declared outside of the if-else block with some defaulting value. What value it takes inside a truthy condition block is another matter.
Answer specific to JS:
Using var will set the variable for hoisting outside of the inner if-else scope (if the same var exists it will be overridden with the new value).
However, let (which you use in your example) declares that the variable will have to exist only inside the inner if-else scope.
Advices:
You should mention the programming language you want to use. Do not force people to guess if you are using some sort of pseudo-code or JS or something else.
Give enough code context
Learn more about JS Scopes, hoisting and closures:
https://www.c-sharpcorner.com/article/scope-closure-hoisting-in-javascript/
https://ui.dev/ultimate-guide-to-execution-contexts-hoisting-scopes-and-closures-in-javascript/
--> both links are providing good examples and context.

How can a function get access to itself?

Is it right, that when the 'inner' function is called in the example that I gave, the JS engine looks for the declaration of the 'inner' function in the current scope(now it is the scope of the 'inner' function). Since there is no declaration of it in the current scope, the JS engine is trying to find the 'inner' function declaration in the outer scope, and the outer scope is exactly the place where the 'inner' function was declared. So is it correct to say, that the 'inner' function can call itself because the scope chain was used?
function outer() {
function inner() {
inner();
}
}
Thanks :)
The outer function is irrelevant for the example given. The following would also work:
function inner() {
inner();
}
So, no. It doesn't get access via the outer function.
what i know is that calling itself will create a new place in the memory, so it's another copy(or lets say kind of instance) from itself, but with another copy of every variable inside it, saying:
function outer() {
function inner(params) {
//ignore existance of the stop condition
//at first call params is 3 then it will be 2
inner(2);
}
inner(3)
}
each one has it's own place in memory and it's own variables

Access Property from External Function

I am trying to setup a feature as follows.
function Class() {
}
Class.prototype.func = function(f) {
var hello = "hello";
setTimeout(f, 1000);
};
new Class().func(function() {
alert(hello);
});
I want the f() function to be able to access the hello variable. The problem is that f() is not running in the context of the func() function.
I have tried using var hello = "hello"; and this.hello = "hello"; but neither work.
How can f() access hello?
Pass it as a parameter
function Class(){
}
Class.prototype.func=function(f){
var hello="hello";
setTimeout(function(){
f(hello)
},1000);
};
new Class().func(function(hello){
alert(hello);
});
Given the structure of the code you've got, there's no way for any "f" passed into "func" to access "hello".
You could however, do this:
Class.prototype.func=function(f){
this.hello="hello";
setTimeout(f.bind(this),1000);
};
new Class().func(function(){
alert(this.hello);
});
JavaScript scoping is based on the lexical relationship between functions (declaring contexts). A variable declared with var is available to the function in which it's declared, and to all functions declared/instantiated within that function. In your case, the anonymous function is not declared inside "func", so no local variable of "func" can ever be visible to it. There's no way to dynamically expose the local scope from inside "func" either. (I generally forget about ignore eval() when answering questions like this, but here I don't think even eval() could work around the situation.)
It can't. The variable simply does not exist in the scope in which the function is defined.
You would need to expose it to a wider scope (e.g. by making it a property of the instance of the Class object or a global).

What is anonymous closure and why is it different from normal closure?

I started reading this: http://www.adequatelygood.com/2010/3/JavaScript-Module-Pattern-In-Depth
And they refer to anonymous closure:
This is the fundamental construct that makes it all possible, and
really is the single best feature of JavaScript. We'll simply create
an anonymous function, and execute it immediately. All of the code
that runs inside the function lives in a closure, which provides
privacy and state throughout the lifetime of our application.
(function () {
// ... all vars and functions are in this scope only
// still maintains access to all globals
}());
I don't understand what happens in a self-executing anonymous
function closure-wise, that is different from a normal closure and
why is it so special?
What is the benefit in it?
Variables that are not defined within a closure get into the window variable and are global.
Example:
var SOME_CONSTANT = 4;
function foo() {
var c = SOME_CONSTANT;
console.log( c );
}
foo();
If you have this code, SOME_CONSTANT will be global to all files and code run within inline scripts etc, which may not be desired.
You can use the self-calling closure to keep the variable only inside this closure:
( function() {
var SOME_CONSTANT = 4;
function foo() {
var c = SOME_CONSTANT;
console.log( c );
}
foo();
} () );
This way you can have modules that have variables global only to that module. For example, by having the code of each file enclosed in such an anonymous function.
there is no difference to a "normal closure" besides the fact, that this function is executed immediately.

What's the difference in this while loop?

What is difference between
while(condition){
var variable;
...
}
and
while(condition){(function(){
var variable;
...
})();}
Can somebody explain me defference?
In the first case the variable is accessible anywhere inside the while (and even after it). In the second case it is private and accessible only inside the auto-invoking anonymous function. So the difference is basically in the scope of the variable. The second example seems pretty convoluted without providing more context.
First example:
while(condition) {
var variable;
... // the variable is accessible here
}
// the variable is accessible here
Second example:
while(condition) {
(function() {
var variable;
... // the variable is accessible here
})();
// the variable is NOT accessible here
}
// the variable is NOT accessible here
Variables have function scope in JavaScript. So in the first loop variable is visible anywhere inside your function—the function that contains the while loop, that is.
In the second one, variable is visible only inside the anonymous function, since that's the function in which it's declared.
In the first case, variable accessible anywhere in the function that encloses the while. That's because JavaScript does not have a local scope, only function scope.
This might be undesirable in some cases and hence the second variant, which encloses the variable (and loop's body) within anonymous function.
The auto calling function basically creates a scope. Variables defined inside it will not be accessible outside the while loop.
var i = 0;
while (i++ == 0) {
var a = "hi a";
}
console.log(a); //hi a
var ii = 0;
while (ii++ == 0) {
(function() {
var b = "hi b";
})();
}
console.log(b); //Uncaught ReferenceError: b is not defined
http://jsfiddle.net/
Got closures to consider as well as Darin Dimitrov comments.

Categories

Resources