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.
Related
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)
Ok so just a quick one... I REAAAAAALLLLY am not understanding scope at all. Do some reason whenever I put a variable inside of a function it's undefined. It seems the only way it works it to declare it OUTSIDE of a function. So what gives? Am I simply misunderstanding the concept of local and global variables? Because it seems global variables are the only ones that work...
Edit:
Simple example...
let a = 'something';
function myFunction() {
// Code block
};
This works 👆
But the following gives me undefined variables:
function myFunction() {
let a = 'something';
// Code block
};
First lets take a look at the differences between local and global variables.
LOCAL VARIABLES - Any variable defined inside of a function or loop. If the variable is defined in a certain function/loop, it can only be accessed in that function/loop.
For example:
function number() {
let a = 0;
// Can access a here.
}
// Cannot access a here.
GLOBAL VARIABLES - Any variable that is not defined inside of any function or loop. These variables can be accessed anywhere.
For example:
let b = 0;
function number() {
// b can be accessed here.
}
// b can be accessed here.
The scope of a variable is where it can be accessed in. For ex, a scope of a local variable that is defined inside of function number() is the number() function since it can only be accessed there.
One more quick thing (Credit to Mikael Lennholm) var doesn't scope a variable to a loop (or any non-function statement block), it only scopes it to the current function. To scope a variable to any statement block you have to use let/const
Now let's look at your examples:
Here is the first example:
let a = 'something';
myFunction();
function myFunction() {
console.log(a);
};
That works fine, and that's what you said.
Here is the second example you said doesn't work:
function myFunction() {
let a = 'something';
console.log(a);
};
myFunction();
But, if you click the run button, you'll actually see it does work, it does get logged. If you after this go and check in the console what the variable a is of course it will be undefined, since a can be only accessed in the myFunction() function, and the console is not in that function.
You said that the script doesn't work, it's most probably because of something else (if it was because of this there would be an error in the console). You can try posting the website here and I can help you.
Hope this helped you :)
Global variables are variables that you have access to them anywhere in your codes.
Local variables are limited to their scopes like a function, module, class and etc.
if you define a local variable it can be accessible in the nested level like closures.
if you define a global variable and you define the same name as local variable , the local overwrite the global, then be careful.
Disclaimer: This question is purely curiosity driven and has to do a lot with how the javascript works.
I understand why the following code works. Due to closures, foo has access to the scope where a resides. This makes sense.
var a = 10
var foo = function(){
console.log(a);
}
setTimeout(foo,1000)
However, i wonder why the following also works (explained right after).
var a = 10
setTimeout(function(){
console.log(a);
},1000)
The function is defined in the argument of the function receiving it and essentially was never a closure to the scope that contains a. We know that when a function receives an argument, it creates a local variable for that argument so for example
var outerVar="5"
var bar = function(a){
//implicitly, var a = outerVar happens here
console.log(a)
}
bar(something);
So following that logic, the function passed to setTimeout couldnt have access to a and yet it does.
Im suspecting that when a function is defined in the argument space what happens is, it realy is defined before being assigned as an argument but have no proof of that. Any pointers highly appreciated.
Thanks a bunch.
It's not exactly closure, but it's close.
Strictly speaking, closure is when a variable's scope ends, but is still enclosed in an inner function that still lives on:
function createTimer() {
let counter = 0;
return function() {
return counter++;
}
}
const timer = createTimer(); // function() { ... }
console.log(timer(), timer(), timer()); // 0, 1, 2
The function in which counter is defined has returned, the scope ended, and under normal circumstances, counter should have died and garbage collected. But the inner function returned from createTimer() still has a reference to it, from the enclosed scope, that is a closure.
In JavaScript, every function has access to all of the scopes of all of its ancestors, this is what you're seeing here.
The function passed to setTimeout() has access to a because a is defined in the scope around it.
When you look at a javascript code and see how it works, the best way according to me is first understand the javascript engine how it works.
First it traverses the code and assigns all the variables to the scope and further more in the second trace it assigns the values based on the scopes.
So in your first code,
The engine first traverses and assigns
var a to global scope,
var foo as global scope,
Then when setTimeout runs it calls foo function and logs the value of a as that of the global a as it doesnt have any local “a” so checks the lexical scoping.
In your second code,
Var a is again global scoped
and no other declaration this time.
In second traverse it assigns the value 10 to a and interprets the settimeout and prints the value
In your third code,
Same as the second one except the fact that instead what “foo” was giving to the settimeout function, you wrote your callback function then n there itself.
By the time l it executed the setTimeout,
Each of your codes have the value for “a” in the global scope that they are accessing.
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.
I am learning YUI and have occasionally seen this idiom:
<script>
(function x(){ do abcxyz})();
</script>
Why do they create a function just to invoke it?
Why not just write:
<script>
do abcxyz
</script>
For example see here.
They're taking advantage of closures.
A short explanation: Since JS uses function-level scoping, you can do a bunch of actions within a function and have it remain in that scope. This is useful for invoking code that doesn't mess with the global namespace. It also allows one to make private variables - if you declare a variable inside of an anonymous function and execute it immediately, only other code inside of the anonymous function can access that variable.
For example, suppose I want to make a global unique id generator. One might do code like this:
var counter = 0;
var genId = function()
{
counter = counter + 1;
return counter;
}
However, now anyone can mess with counter, and I've now polluted the global namespace with two variables (counter and genId).
Instead, I could use a anonymous function to generate my counter function:
var genId = function()
{
var counter = 0;
var genIdImpl = function()
{
counter = counter + 1;
return counter;
}
return genIdImpl;
}();
Now, I only have one variable in the global namespace, which is advantageous. More importantly, the counter variable is now safe from being modified - it only exists in the anonymous function's scope, and so only the function genIdImpl (which was defined in the same scope) can access it.
It looks like in YUI's example code, they just want to execute code that doesn't pollute the global namespace at all.
They want to avoid namespace collisions, I'd guess. Seems as a good practice in JS.