Does Var variables get hoisted out of the IIFE? [duplicate] - javascript

This question already has answers here:
Surprised that global variable has undefined value in JavaScript
(6 answers)
Closed 1 year ago.
I have a block of code and I want to exactly know the running order and why the result like this:
var variable = 10;
(()=>{
variable_3 = 35;
console.log(variable_3);
var variable_3 = 45;
variable_2 = 15;
console.log(variable);
})();
console.log(variable_2);
console.log(variable_3);
var variable=30;
The output for this code is
35, 10, 15, Error
What I understand is:
inside the IIFE we create a global variable_3 and assigned 35.
Then it print out 35.
We create a Var variable_3 inside the IIFE and assigned 45. (Is this Var get hoisted out of the IIFE??)
35.10.15 I understand, can you explain the last number and make my logic correct?
Thanks!

(()=> {
a = 123;
console.log(a); // 123
console.log(window.a); // undefined
var a;
})();
(()=>{
var a = 4;
(()=>{
console.log(a); // undefined
var a = 5;
})()
})()
(()=>{
var source = {};
(()=>{
a = source;
var a;
console.log(a === source) // true
// The variable source is indeed assigned to variable a, although variable a is declared after
})()
})()
var variable is a definition
like function ,
function can use before defined;
main();
function main(){}
so
a = 1;
var a;
like function; use variable before define is also ok;

1.)Basically there are two scopes, that is the local and global scope. The function
scope falls within the local scope.
2.)Hoisting moves declarations to the top of the current scope.
3.)If you assign a value to a variable you have not previously declared, it is automatically declared as a global variable(even if it is within a function) and initialized with the assigned value.
4.)In the local function scope, declaring with var, let or const keywords will all create a local variable. It is only available or accessible within that function.
In your case:
var variable = 10;//global variable declaration, outside the function.
(()=>{
variable_3 = 35;//declares a global variable, ref. (3).
console.log(variable_3);//prints 35, because it is available globally now.
var variable_3 = 45;//re-declaration turns it to local variable, ref. (4).
variable_2 = 15;//declares global variable, ref. (3)
console.log(variable);//prints 10, because it is a global variable.
})();
console.log(variable_2);//prints because it is a global variable
console.log(variable_3);//fail to print because of re-declaration which changed it from a global variable to local function variable.
var variable=30;

Related

Why do some variables declared using let inside a function become available in another function, while others result in a reference error?

I can't understand why variables act so strange when declared inside a function.
In the first function I declare with let the variables b and c with the value 10:
b = c = 10;
In the second function I show:
b + ", " + c
And this shows:
10, 10
Also in first function I declare a with value 10:
let a = b = c = 10;
But in the second function it shows an error:
Can't find variable: a
Now in the first function I declare d with value 20:
var d = 20;
But in the second function it shows the same error as before, but with the variable d:
Can't find variable: d
Example:
function first() {
let a = b = c = 10;
var d = 20;
second();
}
function second() {
console.log(b + ", " + c); //shows "10, 10"
try{ console.log(a); } // Rreference error
catch(e){ console.error(e.message) }
try{ console.log(d); } // Reference error
catch(e){ console.error(e.message) }
}
first()
It's because you're actually saying:
c = 10;
b = c;
let a = b;
And not what you think you are saying, which is:
let a = 10;
let b = 10;
let c = 10;
You'll notice that no matter how many variables you add to your chain, it will only be the first (a) that causes the error.
This is because "let" scopes your variable to the block (or, "locally", more or less meaning "in the brackets") in which you declare it.
If you declare a variable without "let", it scopes the variable globally.
So, in the function where you set your variables, everything gets the value 10 (you can see this in the debugger if you put a breakpoint). If you put a console log for a,b,c in that first function, all is well.
But as soon as you leave that function, the first one (a)--and again, keep in mind, technically in the order of assignment, it is the last one-- "disappears" (again, you can see this in the debugger if you set a breakpoint in the second function), but the other two (or however many you add) are still available.
This is because, "let" ONLY APPLIES TO (so only locally scopes) THE FIRST VARIABLE--again, which is technically the last to be declared and assigned a value--in the chain. The rest technically do not have "let" in front of them. So those are technically declared globally (that is, on the global object), which is why they appear in your second function.
Try it: remove the "let" keyword. All your vars will now be available.
"var" has a similar local-scope effect, but differs in how the variable is "hoisted", which is something you should definitely understand, but which is not directly involved with your question.
(BTW, this question would stump enough pro JS devs to make it a good one).
Strongly suggest you spend time with the differences in how variables can be declared in JS: without a keyword, with "let", and with "var".
In the function first(), variables band c are created on the fly, without using var or let.
let a = b = c = 10; // b and c are created on the fly
Is different than
let a = 10, b = 10, c = 10; // b and c are created using let (note the ,)
They become implicit global. That's why they are available in second()
From documentation
Assigning a value to an undeclared variable implicitly creates it as a global variable (it becomes a property of the global object) when the assignment is executed.
To avoid this, you can use "use strict" that will provide errors when one use an undeclared variable
"use strict"; // <-------------- check this
function first() {
/*
* With "use strict" c is not defined.
* (Neither is b, but since the line will be executed from right to left,
* the variable c will cause the error and the script will stop)
* Without, b and c become globals, and then are accessible in other functions
*/
let a = b = c = 10;
var d = 20;
second();
}
function second() {
console.log(b + ", " + c); //reference error
console.log(a); //reference error
console.log(d); //reference error
}
first();
Before calling things strange, let’s know some basics first:
var and let are both used for variable declaration in JavaScript. For example,
var one = 1;
let two = 2;
Variables can also be declared without using var or let. For example,
three = 3;
Now the difference between the above approaches is that:
var is function scoped
and
let is block scoped.
while the scope of the variables declared without var/let keyword
become global irrespective of where it is declared.
Global variables can be accessed from anywhere in the web page (not recommended because globals can be accidentally modified).
Now according to these concepts let's have a look at the code in question:
function first() {
let a = b = c = 10;
/* The above line means:
let a=10; // Block scope
b=10; // Global scope
c=10; // Global scope
*/
var d = 20; // Function scope
second();
}
function second() {
alert(b + ", " + c); // Shows "10, 10" //accessible because of global scope
alert(a); // Error not accessible because block scope has ended
alert(d); // Error not accessible because function scope has ended
}
Variables using the let keyword should only be available within the scope of the block and not available in an outside function...
Each variable that you are declaring in that manner is not using let or var. You are missing a comma in the variables declaration.
It is not recommended to declare a variable without the var keyword. It can accidentally overwrite an existing global variable. The scope of the variables declared without the var keyword become global irrespective of where it is declared. Global variables can be accessed from anywhere in the web page.
function first() {
let a = 10;
let b = 10;
let c = 10;
var d = 20;
second();
}
function second() {
console.log(b + ", " + c); //shows "10, 10"
console.log(a); //reference error
console.log(d); //reference error
}
first();
It's because of when you don't use let or var then variable is getting declare on the fly, better you declare like following.
let a = 10;
let b = 10;
let c = 10;
The strange issue is caused by scoping rules in JavaScript
function first() {
let a = b = c = 10; // a is in local scope, b and c are in global scope
var d = 20; // d is in local scope
second(); // will have access to b and c from the global scope
}
Assuming that you want to declare 3 local variables initialised to the same value (100). Your first() will look like below. In this case, second() will not have access to any of the variables because they are local to first()
function first() {
let a = 100; // a is in local scope init to 100
let b = a; // b is in local scope init to a
let c = b // c is in local scope init to b
var d = 20; // d is in local scope
second(); // will not have access a, b, c, or d
}
However, if you want global variables then your first() will look like below. In this case, second will have access to all the variables because they are in global scope
function first() {
a = 100; // a is in global scope
b = a; // b is in global scope
c = b // c is in global scope
d = 20; // d is in global scope
second(); // will have access to a, b, c, and d from the global scope
}
Local variables (aka. accessible in the code block where they are declared). A Code block is any {} with line(s) of code between.
function() {var, let, const in here is accessible to entire function},
for() {var in here is accessible to outer scope, let, const accessible only in here},
etc.
Global variables (aka accessible in the global scope).
These variables are attached to the global object. The global object is environment dependent. It is the window object in browsers.
Special note: You can declare variables in JavaScript without using the var, let, const keywords. A variable declared this way is attached to the global object, therefore accessible in the global scope.
a = 100 // is valid and is in global scope
Some articles for further reading:
https://www.sitepoint.com/demystifying-javascript-variable-scope-hoisting/
https://scotch.io/tutorials/understanding-scope-in-javascript
https://www.digitalocean.com/community/tutorials/understanding-variables-scope-hoisting-in-javascript
Main difference is scoping rules. Variables declared by var keyword are scoped to the immediate function body (hence the function scope) while let variables are scoped to the immediate enclosing block denoted by { } (hence the block scope). And when you say
c = 10;
b = c;
let a = b;
c and b have the life span as fun have but a only have block span and if you try to access a by referencing it always show error but c and b are globally so they don't.You'll notice that no matter how many variables you add to your chain, it will only be the first (a) that causes the error.This is because "let" scopes your variable to the block (or, "locally", more or less meaning "in the brackets") in which you declare it.If you declare a variable without "let", it scopes the variable globally.So, in the function where you set your variables, everything gets the value 10 (you can see this in the debugger if you put a break-point). If you put a console log for a,b,c in that first function, all is well.But as soon as you leave that function, the first one (a)--and again, keep in mind, technically in the order of assignment, it is the last one-- "disappears" (again, you can see this in the debugger if you set a break-point in the second function), but the other two (or however many you add) are still available.
Here are the 3 interesting aspects of variable declarations in JavaScript:
var restricts the scope of variable to the block in which it is defined. ('var' is for local scope.)
let allows temporary overriding of an external variable's value inside a block.
Simply declaring a variable without var or let will make the
variable global, regardless of where it is declared.
Here is a demo of let, which is the latest addition to the language:
// File name: let_demo.js
function first() {
a = b = 10
console.log("First function: a = " + a)
console.log("First function: a + b = " + (a + b))
}
function second() {
let a = 5
console.log("Second function: a = " + a)
console.log("Second function: a + b = " + (a + b))
}
first()
second()
console.log("Global: a = " + a)
console.log("Global: a + b = " + (a + b))
Output:
$ node let_demo.js
First function: a = 10
First function: a + b = 20
Second function: a = 5
Second function: a + b = 15
Global: a = 10
Global: a + b = 20
Explanation:
The variables a and b were delcared inside 'first()', without var or let keywords.
Therefore, a and b are global, and hence, are accessible throughout the program.
In function named 'second', the statement 'let a = 5' temporarily sets the value of 'a' to '5', within the scope of the function only.
Outside the scope of 'second()', I.E., in the global scope, the value of 'a' will be as defined earlier.

Scope in JavaScript behaviour

This is a simple script that'll log the content of text from a Photoshop file.
var numOfLayers = app.activeDocument.layers.length;
var resultStr = "";
doAllLayers();
alert(resultStr);
function addToString(alayer)
{
if (alayer.kind == "LayerKind.TEXT")
{
var c = alayer.textItem.contents;
resultStr += c;
}
}
// main loop
function doAllLayers()
{
for (var i = numOfLayers -1; i >= 0; i--)
{
var thisLayer = app.activeDocument.layers[i];
addToString(thisLayer);
}
}
It works fine but I really should be passing a string into the function to add to itself, however it works.
How does the scope of JavaScript allow this to happen? Are declared local variables still accessed by functions or is it another trick I'm missing?
Here are some basic rules to variable scoping in JavaScript:
If defined with the var keyword, the variable is function-scoped. That is, the variable will be scoped to either the closest containing function, or to the global context if there is no containing function.
Example:
// globally-scoped variable (no containing function)
var foo = 'bar';
function test() {
// function-scoped variable
var foo2 = 'bar2';
if (true) {
// still function-scoped variable, regardless of the if-block
var foo3 = 'bar3';
}
// see?
console.log(foo3); // --> 'bar3'
}
If defined with the let keyword (ES6+), then the variable is block-scoped (this behavior more closely resembles most other C-family syntax languages). Example:
// error: top level "let" declarations aren't allowed
let foo = 'bar';
function test() {
// block-scoped variable (function are blocks, too)
let foo2 = 'bar2';
if (true) {
// block-scoped variable (notice the difference
// from the previous example?)
let foo3 = 'bar3';
}
// uh oh?
console.log(foo3); // --> ReferenceError: foo3 is not defined
}
If defined with neither the var or let keywords (e.g., foo = bar), then the variable is scoped to the global context. Example:
// globally-scoped variable
foo = 'bar';
function test() {
// also globally-scoped variable (no var or let declaration)
foo2 = 'bar2';
if (true) {
// still a globally-scoped variable
foo3 = 'bar3';
}
}
test();
console.log(foo, foo2, foo3); // 'bar', 'bar2', 'bar3'
In all of these cases, functions defined within scope of a variable still have access to the variable itself (technically you're creating a closure, as the numOfLayers and resultStr variables are lexically in scope of your addToString and doAllLayers functions).
Please note that the scoping rules are technically a little more nuanced than this, but you're better off reading a more in-depth article at that point.
You have defined var resultStr = ""; outside function which is a global variable. you can access this global variable inside addToString() and start concatenating to it. Note that inside the method you have not declared var resultStr = ""; else it would have been a different variable local to that method.

Variable scope puzzle, prints undefined for variable declared inside function [duplicate]

This question already has answers here:
Surprised that global variable has undefined value in JavaScript
(6 answers)
Closed 8 years ago.
var a = 2;
var b = function(){
console.log(a);
var a = 1;
};
b();
When I call b, it prints undefined. What is the reason?
Inside a function, var declares a function-scoped variable. That means it's visible to the function. The entire function. That means you are print out the variable before assigning a value to it.
var a = 123;
(function () {
a = 456; // Changes the function's "a"
console.log(a); // Outputs the function's "a": 456
var a; // At compile-time, declares a function variable named "a".
})();
console.log(a); // Outputs the global "a": 123
Along the same line, repeating the declaration doesn't do anything. The following prints out 123.
(function () {
var a = 123;
var a;
console.log(a); // 123
})();
The var a in your code is a variable declaration that declares a variable within the scope of its containing function. Due to variable hoisting, variable declarations (like var a) are hoisted to the top of their containing function. While any declaration is hoisted, assignments to that variable are not hoisted, Thus, your code is equivalent to:
var a = 2;
var b = function(){
var a; // hoisted declaration; declares `a` within this function scope
console.log(a);
a = 1; // not-hoisted assignment
};
b();
Since a declared variable is undefined until it is given a value, this code logs undefined.
You have this:
var a = 2;
var b = function(){
console.log(a);
var a = 1;
};
During the run time it becomes:
var a = 2, b;
b = function(){
var a; // new variable declaration with no value assigned
console.log(a); // You used it new "a" without assigning any value
a = 1;
};
Inside the function the a is a new variable because of var keyword and JS is taking this new a in account which is undefined not the global a. Tow variables with same name, one is outside the function (in global scope) and another is inside the function. Since there is a new variable available inside the function so it's being used in console.log(a) but no value assigned.
You may read JavaScript Scoping and Hoisting and var on MDN.

Puzzled by this JavaScript code snippet

For this snippet, I'm not surprised global variable 'a' evaluates to be 5.
http://jsfiddle.net/MeiJsVa23/gZSxY/ :
var a = 10;
function func(){
a = 5;
}
func(); // expect global variable 'a' to be modified to 5;
alert(a); // and this prints out 5 as expected. No surprise here.
​
But how come for this code snippet, global variable 'a' evaluates to be 10 and not 5? It's as if the a = 5 never happened.
http://jsfiddle.net/MeiJsVa23/2WZ7w/ :
var a = 10;
function func(){
a = 5;
var a = 23;
}
func(); // expect global variable 'a' to be modified to 5;
alert(a); // but this prints out 10!! why?
​
This is due to variable hoisting: anything defined with the var keyword gets 'hoisted' to the top of the current scope, creating a local variable a. See: http://www.adequatelygood.com/2010/2/JavaScript-Scoping-and-Hoisting
So, there are two things are going here: hoisting and shadowing.
Because the first one, variable declarations are "hoisted" to the top, so your code is equivalent to:
var a = 10;
function func(){
var a;
a = 5;
a = 23;
}
And because the second one, you're "shadowed" the global variable a with a local ones, so the changes are not reflected to the global a.
This is called "variable hoisting". var declarations (and function() declarations) are moved to the top of their scope.
This has to do with hoisting.
In the function, a local variable with the same name is declared. Even though it happens after your modification, it is deemed to have been declared before it - this is called hoisting.
Local variables hoist for declaration but not value. So:
function someFunc() {
alert(localVar); //undefined
var localVar = 5;
}
Functions, if declared with function name() {... syntax, hoist for both declaration and value.
function someFunc() {
alert(someInnerFunc()); //5
function someInnerFunc() { return 5; }
}
var a = 10; //a is 10
function func(){
a = 5; //a is 5
var a = 23; // a is now in local scope (via hoisting) and is 23
}
func();
alert(a); // prints global a = 10
Presumably, the statement var a = 23 creates a local variable for the whole scope. So the global a is shadowed for the entirety of func(), not just for the lines below the statement. So in your second snippet, a = 5 is assigning to the local variable declared below.

What scope are variables globally defined by "var"?

In Javascript, if I declare variables with var in javascript outside of a function
var foo = 1;
var bar = 2;
function someFunction() {
....
}
are those variables within the scope of the document or the window? Furthermore, why does this matter? I know that if one declares a variable without var, then the variable is global.
Is there a simple way for me to test whether a variable falls within the scope of the document or the window?
var limits the scope of a variable to the function it was defined in, so variables defined at the top level with var will effectively have global scope.
If you assign a value to a variable that hasn't been scoped with var then it becomes global regardless of where you define it.
There is a good article on javascript scopes here: What is the scope of variables in JavaScript?
When you declare a function in JavaScript, it creates a scope.
When you declare a variable, it must have a var. The var determines what scope it belongs and where it is visible. If it has no var, then it's an "assignment" to a variable and the browser assumes that a variable with that name exists in the outer scopes.
When an assignment happens, the browser searches outwards until it reaches the global scope. If the browser does not see the assigned variable in the global scope, it will declare it in the global scope (which is not good)
for example, take the following as a demo of scope visibility and not actual working functions:
//global variables
var w = 20
var x = 10
function foo(){
function bar(){
//we assign x. since it's not declared with var
//the browser looks for x in the outer scopes
x = 0;
function baz(){
//we can still see and edit x here, turning it from 0 to 1
x = 1;
//redeclaring a variable makes it a local variable
//it does not affect the variable of the same name outside
//therefore within baz, w is 13 but outside, it's still 20
var w = 13;
//declaring y inside here, it does not exist in the outer scopes
//therefore y only exists in baz
var y = 2;
//failing to use var makes the browser look for the variable outside
//if there is none, the browser declares it as a global
z = 3;
}
}
}
//w = 20 - since the w inside was "redeclared" inside
//x = 1 - changed since all x operations were assigments
//y = undefined - never existed in the outside
//z = 3 - was turned into a global
var foo = 1;
window.foo === foo;
JavaScript is a functional language and therefore any variable declared inside the scope of a function is only available in that function.
JS will actually go through each functions scope and look for a variable declared.
function setGlobal() {
bar = 1; // gets set as window.bar because setGlobal does not define it
}
setGlobal();
// logs true and 1
console.log(window.bar === bar, bar); ​
http://jsfiddle.net/kXjrF/
So...
function logGlobal() {
var bar;
console.log( foo, window.foo ) // undefined, undefined
function setGlobal() {
// window.foo is now set because logGlobal did not define foo
foo = 1;
bar = 2; // logGlobal's bar not window.bar
function makePrivate() {
var foo = 3; // local foo
console.log( foo ); // logs 3
}
makePrivate(); // logs 3
}
setGlobal();
console.log( foo, window.foo ); // logs 1, 1
}
as JavaScript has only function scope, variables defined by the var keyword are scoped to the containing function.
you can easily check for global scoping by opening the JavaScript console in the browser (or directly in your code), and typing:
varRef && console.log(varRef)

Categories

Resources