Global:: When someone says global, what comes to your mind? You may visualize a globe you remember seeing in high school. For those who never went to a high school, have a look at Image -1.
Global Star:: Look at image -2. If you cant see a person in the top right corner, borrow a magnifying glass from your grandma - it's Jackie Chan, the celebrity. He is a global star. People will recognize him from any part of the world. Similarly, you can easily recognize a global star like Nelson Mandela, Princess Diana, etc.
Global Variable:: Global variable is exactly like global star. You can access it (get or set the value of it), from any part of your application.
Image-1: The Globe
Image-2: The Global Star
Image-3: Mr. Jackie Chan
Global Events:: If you are not a genius like me, you can easily recognize global events like "New Year's Day", "Christmas", "The Olympics", etc. from any part of the world. Have a look at Image -5.
Global Functions:: Similarly, global functions could be accessible from any part of your application.
Global Scope:: Anything in the global scope could be accessible accross your application. Have a look into Image -6. You can have global variables like global stars and global functions like global events/activities.
Image-4: Happy New Year
Image-5: The Global Things
Image-6: The Global Scope
In the code block below, "a" is a global variable and "b" is a global function. You can access global variable from anywhere of your application including inside of the function "b". Anything that is not inside of a function, is global.
//global variable
var a = 2;
//global function
function b(){
console.log(a); //access global variable
}
b(); //execute global function.
Global variables are exactly like global stars. You can access them (get or set the value of it), from any part of your application. Global functions are the same as global events. You can execute (call) them from any part of your application.
Global variables and functions are executed in the global context. If you need to understand more about JavaScript context, read Execution context and Stack in JavaScript or watch Understanding JavaScript this in a crystal clear way
Local:: When somebody says local, what comes to your mind? If you are smart like me, you will thik- not global. Envision about a part of the world. For example, the USA, it's a country, or a part of the world ( If you don't know where is the USA is located, I marked it for you in Image -7).
Local Star:: Look at image -8. If you are in the USA, you may know this infamous celebrity ( she somehow manages to make the tabloids). But people outside of the USA will not recognize her. She is a local star, boudn to her territory.
Local Variable:: Local variables are exactly like local stars. You can only access one (get or set the value of it)- in the local scope. In JavaScript local scope is defined by a function. If you declare a variable inside a function, you can only access it (get or set the value) inside of the function. If you try to access it from outside of the function, you will get a reference error.
Image-7: The Local
Image-8: Kim Kardashian
Image-9: The Local Star
Local Events:: Consider American football (Image-10). Not the football (soccer) the rest of the world knows. It's crazily famous here in the USA, particularly the final events, the Super Bowl. But people outside of the world doesn't know much about it, making the Super Bowl a Local Event.
Local Functions:: Similarly, any function inside another function is called a local function. You can only execute it inside the outer function. If you really want to get the inner function, you have to return the function by creating closure (stay tuned for closure information).
Local Scope:: Anything in the local scope (inside a function) is only accessible from within. Have a look at Image-11.
Scope Chain:: Local scope is connected to the global scope. In Image-12, see a dotted line/chain towards the global scope. This is how you have access to any global variables/functions. This link/chain is called the scope chain (stay tuned for more on the scope chain).
Image-10:Local Events
Image-11:Local Events
Image-12:Local Scope
In the code block below, "d" is a local variable. You can access it (get or set the value) inside the function "b". If you try to access it outside of the function, you will get a reference error.
var a = 2;
function b(){
var d = 21; //local variable
console.log(d); //can access it inside the function
}
b(); // 21
console.log(d); //ReferenceError: d is not defined
Implicit Global:: If you forget to put var before the variable of a function, it becomes a global variable. In the code block below, "a", "f" and "i" are global variables. However, you may not want "f" and "i" to be global. So, be careful. "f" becomes global variable as you put ";" after the value of "e", you might want to add a comma in this place.
var a = 21;
function b(){
var d = 7,
e = 8;
f = 9;
for(i =0; i<5; i++){
console.log(e);
}
}
Local variables are exactly like local-stars. You can only access them (get or set their values) inside their scope. Local functions are like local events. You can only execute (celebrate) inside the scope.
Local variables and functions are executed in the local context.
Multiple functions:: If you have more than one functions and you execute them, each one of them will create their own scope. However, every execution scope will be linked to the global scope. Thats is how you have access to the global scope variable and function from any part of your application. Have a look at Image -13.
Nested Scope:: If you execute a function within a function, the inner function will create a scope inside the outer function. Look at the Image-14. Remember, the inner scope will have access to the outer function variable, while the outer one will have access to the global variable. Now take a minute to absorb Image-14 and take another minute to sift through your confusion.
Closure:: If you have a function inside a function, this is called closure. Closure is a powerful feature of JavaScript for encapsulation. Some of your function could be closure (Image-15). Don't worry about it for now, Soon you will have a crystal clear understanding of closure.
Image-13: Multiple Scope
Image-14: Nested Scope
Image-15: JavaScript Scope
In the code block, below function "b" and function "c" create separate scopes like you see in Image-13
var a = 2;
function b(){
console.log(a);
}
function c(){
console.log(a);
}
b(); // scope created for executing function "b"
c(); // scope created for executing function "c"
In the code block below, when executing of function "b", function "dog" will be executed and it will create a new scope within the scope of function "b". Refer to Image-14
var a = 2;
function b(){
var d = 21;
function dog(){ console.log(a); }
dog(); //closure is created
}
function c(){ console.log(a); }
b();
c();
Block scope is a block/ part of a code surrounded by {}. JavaScript doesn't support block scope. Read more about block scope at MDN: block scope
function getY(){
var x = 5;
if(x>0){
var y = 7;
}
return y;
}
getY(); //7
Congratulations to you! Because JavaScript does not support block scope, it is that much easy to understand. It is less complex and faster to parse. Hoisting also plays a role in this, but we will have to come back to that another time (sorry, too many promises).
JavaScript cannot use block scope but you can have a block scope variable when ES6 "let" is supported by major browsers. Read MDN documents to learn more about let.
You will have as many function scopes as the functions you have executed. Functions inside functions create nested scopes inside the outer function scopes. There would be a new scope, even a function calls itself. However, you will have only one global scope.
Consider the situation - you wake up Saturday afternoon and start looking for car keys ( for whatever reason, you completely forgot what you did Friday night). You might search in the following steps-
If you find the keys inside your room you will not go to check the keys holder or outside.
Image-16: Searching Key
Image-17: Key Holder
Image-18: OutSide
Since local scope is the first place to look for a variable, the local variable gets priority over global and parameter.
var x = 9;
function getX(x){
var x = 7;
return x;
}
getX(5); // 7
The order of accessing a variable is local variables (inner scope), parameters, outer scope(s) then as a last resort, the global variable (window). If your variable doesn't exist in the global scope, JavaScript will return an undefined.
Climbing through the Scope Chain: If you are asking for a global variable from inside of a function, you are climbing through the scope chain. In the code example you are climbing the scope chain for 1,000,000. Every single time, you have to check the local scope, parameters and then get outside of the function. If you are inside of multiple nested functions, then it becomes even more expensive.
var myArr = [0,1,2,3, ...., 1000000];
function getSum(){
var sum = 0;
for (var i =0; i<1000000; i++){
sum += myArr[i];
}
return sum;
}
getSum();
In such expensive cases, you can have a local copy of the global variable. In that case you dont have to climb through the scope chain again and again. Avoid some unnecessary walking.
var myArr = [0,1,2,3, ...., 1000000];
function getSum(){
var sum = 0;
var localArr = myArr;
for (var i =0; i<1000000; i++){
sum += localArr[i];
}
return sum;
}
getSum();
If you are accessing global variable over and over, have a local copy of the global variable. If you are doing it just once or twice, you can ignore these minor performance tips.
Hoist is a verb meaning to raise. A hoist is also a noun, for example a rope and pulley (Image -19). This type of hoist is used in the factories to raise heavy things. One benefit of raising something to the ceiling is that you can see it from any part of the room/factory. You can also hang/hoist your bike for storage during the winter (Image-20)
JavaScript does the exact same thing to hoist (raise) a variable declaration and a function declaration to the top of a function scope. Those variables and functions can be used from any part of the function without raising no reference Exception.
Image-19: Mechanical Hoist
Image-20: Hoisting Bike
Image-21:Ant Hoist Power
In the code block below, the variable "b" is declared after the return statement. If you execute the foo function, you will not receive the no reference error. If you dont trust me, copy this code and run it at your console.
function foo(){
return b;
var b = 7;
}
foo(); //undefined
While creating Context of a function, JavaScript execution engine, scan through the whole function and brings the variable declaration to the top of the scope. Please note the value assignment will not be hoisted. Only the variable declaration is hoisted. And the variable gets the default value of unassigned, variable which is "undefined". Hence, you will get "undefined" returned as the value of "b".
function foo(){
var b;
return b;
b = 7;
}
foo(); //undefined
Similarly if you assign a function to a variable (function expression) only the variable part will be hoisted. However if you have a function declaration, the full function will be hoisted.
You can google more about it or read spec or explore V8 code. And if you find any good materials, please let me know.
In the following code block, you have a function expression where the function is assigned to a variable "bar", a function declaration named "foo" and a variable "a".
function myFunc() {
var bar = function() {
return 'world';
};
function foo() {
return 'fooed';
}
var a = 5;
}
The function declaration of the function foo will be hoisted to the top, followed by the variable bar (from function expression) and variable "a". Post-hoisting, the above mentioned code will look like-
function myFunc() {
function foo() {
return 'fooed';
}
var bar;
var a;
bar = function() {
return 'world';
};
a = 5;
}
Question: what will you see in the console for the following example?
var a = 1;
function b() {
a = 10;
return;
function a() {}
}
b();
console.log(a);
Answer: 1
function a(){}
is hoisted first and it behaves like var a = function () {};
, hence in local scope a
is created.a = 10;
, you are setting the local variable a
, not the global one.Hence, the value of global variable remain same and you get, 1 in the log. ref: js hoisting/scope
Only the declaration of a variable is hoisted. The value assigned remains at its location. A function declaration is hoisted. If you have a function expression only the variable part of the function expression will be hoisted.
If you have a function within a function, execution of the inner function will create a scope inside of the outer function- a nested scope. Because the inside function scope is enclosed by the outer function scope, the inner function scope is called a closure (I invented this definition). Remember, to be a closure, you dont have to return a function, you just have to call a function inside a function.
function a(){
function b(){
console.log('closure');
}
b(); //creates closure
}
Closure Example:: Closure is a powerful feature of JavaScript. Let's have a look into the following example. We have a outer function called "counter" that has a local/private variable "i" and it returns a function (the returning function doesn't have a name and is known as the anonymous function). Inside the returning function (the inner function) returns the value of i and increases it by 1. Aha, very simple!
function counter(){
var i = 0;
return function(){
return i++;
}
}
Step-1: In the following code, we execute a counter function and assign the result of the counter to a variable "a". Hence, the value of "a" will be the inner function (returning function). Just remember the inner function returns the value of "i" and also increase the value of "i". Hence, when you execute the function "a", you will get the value of "i".
Step-2: Now if you execute function "a" (execute inner function), it will return 0 (value of i) and will increase it by 1. If you execute function "a" again it will return 1 (current value of i) and will increase the value of "i" by 1. Hence, in your subsequent call you will get 2, 3, 4, 5 ....
This means, closure holds the state of the local/private variable in the outer scope. And every time, you call it you get the value of "i" increased by 1. Have a look at Image-22 and try to understand it. If you don't get it the time around .... try, try again!
var a = counter();
a(); //0
a(); //1
a(); //2
a(); //3
a(); //4
a(); //5
Now you can have another variable "b" and assign the execution result of the function counter. If you execute "b" (the inner function of the counter), you will get 0. If you execute "b" again, you will get 1. followed by 2, 3, 4, ...
var b = counter();
b(); //0
b(); //1
b(); //2
b(); //3
This means, each closure maintains separate private variables of the outer function. This is a very powerful feature of JavaScript. Have a look at Image-23
Image-22: Scope inside Scope
Image-23: Separate Privacy
Image-24: Closure is Fun
Encapsulation:: You would not be able to access (get or set) the value of "i" from outside. Hence the privacy of the value of "i" is maintained secretly. This is called encapsulation in object oriented programming.
Don't use a closure when you dont need a closure. And don't create too many nested scope. Why do more than you need? (Image-24)
Don't hold excessively large private memory. This could cause memory leak
//try to avoid this
function a() {
var largeStr = new Array(1000000).join('x');
return function () {
return largeStr;
};
}
If you execute a function inside a function, a closure is created. It is not necessary to return a function in order to create a closure..
Closure saves the state of the outer function variable but does not expose those private variables. Now you can hide implementation detail while using closure. This is called encapsulation.
Scope:: Scope determines the variable access of a function when it is executed. It depends on where and how a function is executed. Scope is unique to each execution.
Context:: Context depends on how the function is called. The laymen version of context is the value of "this". If you want to learn more, read Execution context and Stack in JavaScript or watch Understanding JavaScript this in a crystal clear way
JavaScript Identity resolution and Scope chain, Understanding Scope and Context, Variable scope explain, MDN: Functions and function scope
Disclaimer: I promised you will be able to explain to your grandma but i didn't promised that she will understand.
Feel free to express your anger (sorry folks, you have to use g+.). Also point out my mistakes ( technical, wrong answer, spelling, grammar, sentence..., whatever), let your dude learn and grow.