THE BEST COURSE ON UDEMY
Go beyond the basics to uncover the intricate workings of these variable keywords. Few developers grasp their full potential, and even fewer understand how variable creation operates under the hood.
Understand global scope, local scope, blocks and function execution contexts and how to use JavaScript variables in these scenarios
By the end of this course, you’ll not only master the syntax of variables, but also gain a profound understanding of how variable keywords interact with memory, execution contexts, and environment records.
THE BEST COURSE ON UDEMY
Go beyond the basics to uncover the intricate workings of these variable keywords. Few developers grasp their full potential, and even fewer understand how variable creation operates under the hood.
Understand global scope, local scope, blocks and function execution contexts and how to use JavaScript variables in these scenarios
By the end of this course, you’ll not only master the syntax of variables, but also gain a profound understanding of how variable keywords interact with memory, execution contexts, and environment records.
Understanding VAR, LET, and CONST variable keywords is essential for any serious JavaScript developer because these keywords fundamentally shape how variables behave in your code. Understanding their differences in scope, hoisting, and mutability helps prevent common pitfalls. With VAR being function-scoped and prone to hoisting issues, while LET and CONST offer block-scoping and “partial-immutability” (with CONST), developers can write cleaner, more predictable code. Additionally, knowing how these keywords interact with memory management and execution contexts allows developers to optimize performance and maintainability in their applications.
WHAT YOU WILL LEARN:
Fundamentals of
Fundamentals of BLOCK and FUNCTION scope: Delve into the technical logic and contexts that are created whenever the JavaScript engine evaluates variables inside of a block or function.
Advanced Concepts: Gain insights into declarative records, components, slots, and more as you explore advanced topics that every JavaScript developer should know. Part of this advanced learning is understanding the difference between immutable bindings vs immutable assignments, which is extremely important when using the CONST keyword.
Execution Contexts & Call Stack Visualization: Visualize how JavaScript executes your code and how JavaScript variable bindings are created in different contexts.
Hoisting, Binding, and Memory Allocation: Master the concepts of variable hoisting and binding, and learn how memory is allocated differently for each keyword.
The Evolution of JavaScript: Discover why LET and CONST were introduced to replace VAR and what this means for modern development practices.
Temporal Dead Zone (TDZ): Understand this critical concept and learn strategies for effectively managing it in your code.
Comparative Analysis: Compare JavaScript variable scopes with other programming languages like C, Java, and Bash to enhance your understanding of scope management.
Contextual Keyword Selection: Develop the skills to choose the appropriate keyword based on specific coding scenarios.
Memory Management & Bindings: Grasp how memory management works in relation to
Variable Reassignment & Redeclaration: Understand the nuances of variable reassignment and redeclaration in JavaScript depending on whether you're using Dynamic Scoping: Explore these two scoping types to deepen your understanding of variable accessibility.
Historical Insight: Was VAR ever broken? Dive into its past to understand its limitations and how they shaped modern JavaScript.
AND MORE.
COURSE FEATURES:
This course is designed to be interactive and engaging.
Each section is packed with coding exercises that reinforce your learning. You’ll also find quizzes at the end of each section to test your knowledge, a comprehensive final exam to challenge your skills, and a hands-on assignment that puts your newfound expertise into practice.
Join this course to start an exciting adventure as we demystify JavaScript’s reserved variable keywords.
Whether you’re a beginner looking to solidify your foundation or an experienced developer eager to deepen your understanding, this course will equip you with the knowledge and skills needed to excel in JavaScript development.
WHY THIS COURSE STANDS OUT
This isn’t just another course; it’s a transformative experience that will make you an indispensable asset on any development team. Every JavaScript developer uses
Let’s get coding.
Variables in JavaScript are fundamental elements that store data values, and their behavior is influenced by the execution context, which is the environment in which the code runs.
The concept of temporal dead zones (TDZ) applies to let and const, which cannot be accessed before their declaration due to hoisting.
Scope defines where variables can be accessed.
Understanding these concepts is essential for effective JavaScript programming.
The Temporal Dead Zone (TDZ) refers to the period within a block scope where variables declared with let and const cannot be accessed until they are initialized. This zone begins at the start of the block and ends when the variable is assigned a value. Accessing a variable within this zone results in a ReferenceError, emphasizing the importance of declaring variables before use. Unlike var,which is initialized to undefined, let and const variables remain inaccessible until their declaration is reached.
The var keyword has been part of JavaScript since its inception, allowing for function-scoped variables but lacking block scope, which could lead to unintended behavior. With the introduction of ES6 in 2015, the let and const keywords were added to provide block-scoped variable declarations.
The lifecycle of a variable in JavaScript consists of three key stages: Declaration, Initialization, and Assignment.
This concept leads to the million dollar question ...
One reason JavaScript "hoists" functions and places their declarations and initializations into memory is to enable function recursion. When a function is declared, it is available for invocation throughout its scope, regardless of where the call occurs in the code. This means that a function can call itself or another function that has not yet been defined in the code, allowing for recursive patterns.
Hoisting usually applies to variable declarations, not initializations. However, when it comes to VAR, things behave a little differently.
In JavaScript, the execution context is a crucial concept that defines the environment in which code is executed. It consists of two main phases: the Creation or Memory-Allocation Phase and the Execution Phase.
It's during the memory allocation phase that hoisting takes place.
Using the debugger statement in JavaScript allows developers to pause code execution at specific points, enabling them to inspect the current scope of functions and variables. When the debugger keyword is encountered, it triggers the browser's built-in debugging tools, similar to setting a breakpoint, where developers can examine the values of variables and the call stack at that moment.
variables declared with var are initialized with the value of undefined during the hoisting process, which occurs in the Creation Phase of the execution context.
The question that arises is ... why? Why did the creators of JS decide that it should obtain a value during hoisting?
I want you to start visualizing what happens when you declare a variable with VAR, and also what happens when you reassign and redeclare values using VAR.
The let keyword in JavaScript allows for the reassignment of variables but does not permit their redeclaration within the same scope. This means that after a variable is declared with let, you can assign it a new value later, but attempting to declare it again with let in the same scope will result in a syntax error.
The const keyword in JavaScript prevents a variable from being reassigned to a different value, meaning that once it is set, you cannot change its reference. However, this does not imply that the value itself is immutable; you can still modify the properties of objects or elements within arrays declared with const
In JavaScript, scope refers to the context in which variables are accessible and determines their visibility throughout the code. There are four primary types of scope: global scope, where variables can be accessed from anywhere in the program; function scope, where variables declared within a function are only accessible inside that function; module scope; and block scope, introduced in ES6 with let and const, which restricts variable access to the block in which they are defined.
When you use VAR, what you're doing is attaching your variable to the global object. In the context of browsers, this will be the window object.
Adding properties to the global object is generally not advisable because it can lead to name collisions, where a variable unintentionally overrides an existing global property, causing unpredictable behavior. This is particularly problematic in JavaScript, where many built-in functions and properties exist on the global object (like window in browsers). Additionally, global variables can make code harder to maintain and debug, as their values can be changed from anywhere in the codebase, leading to potential conflicts and making it difficult to track the flow of data. Moreover, using global variables increases the risk of spaghetti code, where the interdependencies between different parts of the code become tangled and unclear, complicating future modifications or debugging efforts.
In JavaScript, function scope applies to variables declared with var, let, and const when they are defined within a function. All three types of declarations are confined to the function in which they are declared, meaning they cannot be accessed from outside that function.
I want to start showing you different programming languages. Why? Well, I want you to become a true coding Grandmaster and the more exposure you get, the faster you're development will be.
In this lecture I want to show you that VAR is unique in JavaScript in that it is only function scoped - NOT block scoped. This is different to other programming languages like C for example, where variables are blocked scope.
In JavaScript, module scope refers to the accessibility of variables declared within a module, where var, let, and const are all confined to that module. This means that any variable declared using these keywords within a module cannot be accessed from outside the module, promoting encapsulation and preventing global namespace pollution.
Block scope in JavaScript refers to the visibility of variables declared with the let and const keywords, which are limited to the block in which they are defined, typically enclosed in curly braces {}. This means that variables declared with let or const cannot be accessed outside of their respective blocks, preventing unintentional interference with variables in other scopes.
In this lecture I'll show you that other languages such as JAVA also have blocked-scoped variables.
Back in the day, when we only had VAR, we had to be creative in 'tricking' the parser to treat our variable as block-scoped. However, it made for messy code.
Bottom line: even though you can lexically define let and const and VAR in the same block, they are treated differently in terms of scope by the JavaScript engine.
Stay motivated, grab a coffee, and keep going!
I want to prove to you that VAR is not blocked scoped by using a simple IF statement in global scope.
Nested scopes refer to the hierarchical structure of variable accessibility in programming, where functions or blocks are defined within other functions or blocks. This creates a chain of scopes, allowing inner functions to access variables from their own scope as well as from any outer scopes.
Shadowing occurs when a variable declared in an inner scope has the same name as a variable in an outer scope, effectively hiding the outer variable. In this case, any reference to the variable name within the inner scope will refer to the inner variable, which can lead to confusion and unexpected behavior.
The Temporal Dead Zone (TDZ) was created in JavaScript to enhance error handling and promote safer coding practices. It refers to the period between the start of a block scope and the point where a variable declared with let or const is initialized. During this time, accessing the variable results in a ReferenceError, preventing unintended use before declaration.
The term "temporal" comes from latin that refers to time. This period occurs between the creation of a variable and its declaration within a block scope, where attempts to access the variable result in a ReferenceError.
This lecture is going to be exciting, because I'll show you a practical example of why its referred to as "temporal".
Knowing this is important, as it emphasizes the importance of timing in variable initialization and access.
In the final example of this section, I want to introduce you to different concepts such as execution contexts, records, and more!
In this lecture let's write the code, and I want you to identify the different type of scopes we have created.
In the previous lecture we created 4 different types of scopes. The top-level scope is the Global Scope.
In this lecture I want you to assign a scope that each and every variable declaration (and function and block declaration) is attached to.
Good luck.
For the first time in this course, I want you to start visualizing what happens when a script starts to execute.
As you'll learn in this lecture, a Global Execution Context (or GEC) is created every time a JavaScript file is executed. There will typically only be one GEC for every JavaScript program running.
When the creation phase is done (in other words, when the JavaScript engine has "hoisted" or allocated "memory" for all variables) then that execution context will be placed on the call stack and code can start executing.
Once our code starts to execute, variables in current scope will be assigned their values, in the order you defined them in code.
In our particular example, we hit a function call.
When this happens, a new function execution context gets created and again the JS engine has to hoist or place into memory variable declarations. Once done, this function execution context has to also be placed on top of the execution call stack.
In the final example lecture, you'll see what happens when a block is reached inside of a function.
I will also illustrate that JavaScript implements "lexical" scoping, where the parser will look at the [[OuterEnv]] field of each environment to determine where to look for a variable's value.
We have covered a ton of information in this section, so pat yourself on the BACK and keep going.
See you in the next section.
Congrats!
You're on your way to mastering the stages of variable creation and exploring the nuances of defining variables with var, let, and const.
Now, it’s time to put your knowledge to the test and see how well you've been paying attention.
In the next section, we’ll dive deeper into understanding execution contexts, realms, lexical environments, and variable environments.
We’re just getting warmed up!
See you in the next section.
You'll hear many developers say that "hoisting" is when the JS engine moves your variable declarations to the top of their respective scopes.
This is ... wrong.
Let me explain.
In this lecture I want to show you what the definition of VAR is, and introduce you to the execution context.
A quick word on why its so important for you to learn the concepts taught in this section. The reasons may surprise you.
For every JavaScript program you run, a new Global Execution Context will be created by the JS engine. There can only ever by one GEC for every JavaScript program.
As you'll see in this lecture, a GEC contains many components, but the most important are Realm, Lexical Environment and Variable Environment.
An execution context goes through two main key stages - the creation phase, and the execution phase.
In JavaScript, a Realm Record refers to an isolated environment where execution contexts operate, containing intrinsic objects and a global environment. Each execution context, whether global or functional, is associated with a realm, ensuring that code runs in its own scope without interference from other realms.
Every execution context contains a Realm, that points to a Realm Record.
The 3 most important fields that it creates that helps us understand VAR, LET and CONST are:
Global Environment Record: This field holds the global object and provides access to global variables and functions within the realm.
Intrinsic properties: These include built-in objects like Array, Function, and Object, which are available for use within that specific realm's execution context.3
Global object.
The [[Intrinsics]] field in the realm record is a collection of well-known intrinsic objects that are defined by the ECMAScript specification and associated with the current realm. These intrinsics provide foundational functionalities, such as built-in constructors and functions, and are essential for the operation of JavaScript code within that realm. Each realm can have its own set of intrinsic objects, ensuring consistent behavior across different execution contexts.
The [[GlobalObject]] field in a realm record represents the global scope for that specific execution context, providing access to variables, functions, and objects defined globally. Each host environment (e.g., browsers or Node.js) has its own global object, such as window in browsers and global in Node.js.
Environment Records in JavaScript are specification types that define the association of identifiers (variables and functions) to their values within a lexical environment. Each Environment Record contains an [[OuterEnv]] field, which references an outer environment record or is null if it is the global environment.
The GlobalEnv field within the record realm of the JavaScript execution context refers to the global environment where all global variables and functions are stored. This environment is created when the JavaScript engine first loads the code, establishing a default execution context. It includes the global object (e.g., window in browsers) and the this keyword, allowing access to global variables and functions throughout the script
As you know, if you use the VAR keyword or function keyword within top-level of your script, it will be managed by the object environment record.
If you use LET or CONST, on the other hand, well, they are managed by a different record - the declarative environment record.
The [[VarNames]] field in the JavaScript execution context holds the names of VAR variables, and function declarations, that are declared within that context. It serves as a reference for variable lookups, enabling the engine to efficiently manage scope and access variables during code execution.
The Lexical Environment in JavaScript is a structure that maps variable and function identifiers to their values, consisting of two parts: an Environment Record, which stores local variables, and a reference to the outer lexical environment. This allows functions to access variables from their defining scope, enabling closures. The Variable Environment, on the other hand, specifically manages variable bindings for var declarations, distinguishing it from the Lexical Environment's broader role in tracking all identifiers.
I want to have a look at a simple example where we load a blank html file, with a blank JavaScript file.
I want you to think about what things will get created, taking what you've learned about the global execution context.
In this lecture we will look at a block of code, and walk through the first stage of the global execution context creation phase - setting up the various components necessary to manage the execution of your JS code in this global scope.
In this lecture we will assign the variables and functions to their correct positions within the Realm.
Whenever you create an "object" in JavaScript that can be "called", it is referred to as a function ... more technically, a "function object".
I'll show you the exact clauses in ECMAScript that confirm this.
A function object contains a few internal slots that are used during the execution phase (next section).
Great Job!
Congratulations on completing this challenging section!
Very few developers possess the understanding you now have.
Every execution context in JavaScript goes through two stages: creation and execution. Did you know, this concept isn't unique to JavaScript? Yep, many other languages, such as Java, Python, C#, and Ruby, also follow a similar pattern of preparing an environment for execution before running the actual code, even though the specifics may vary.
The creation phase is often referred to by developers as "hoisting."
However, it's important to note that hoisting doesn't involve the JavaScript engine moving your code around. Instead, it refers to the engine creating bindings for all variables declared within a specific scope.
In the next section, we will explore the final phase of the execution context: the execution phase.
Good luck, and see you in the next section!
After the JS engine has created all bindings for all variables and functions in global scope, it enters the next phase and that is ... the execution phase.
During this phase your variables will be allocated their values lexically, and new function calls will create new execution contexts that are added to the call stack.
In this lecture let's look at a block of code, and evaluate the execution context: creation phase
Every time a function is invoked, the internal slot [[Call]] is executed. It is this [[Call]] slot that creates a new execution context, a new function environment record and all other things necessary for the JS engine to keep track of code execution inside of functions.
We have now reached the execution phase of the execution context.
To finish off this section, let me walk through all the concepts we've covered thus far in the course, from the perspective of a developer.
You've done it!
You have now mastered the concepts of variable creation and execution in JavaScript.
This knowledge empowers you to understand the behavior of var, let, and const in both global scopes and functions.
In the next section, we will build on this foundation by exploring practical examples and examining how the JavaScript engine handles blocks ... a topic that very few developers ever want to tackle!
Enjoy the upcoming questions, and I look forward to seeing you soon!
Clyde
In this lecture, you'll see firsthand how far you've come in understanding advanced concepts related to VAR.
Do you remember that at the very beginning I showed you the definition of VAR as per ECMAScript:
A var statement declares variables that are scoped to the running execution context's VariableEnvironment. Var variables are created when their containing Environment Record is instantiated and are initialized to undefined when created. Within the scope of any VariableEnvironment a common BindingIdentifier may appear in more than one VariableDeclaration but those declarations collectively define only one variable. A variable defined by a VariableDeclaration with an Initializer is assigned the value of its Initializer's AssignmentExpression when the VariableDeclaration is executed, not when the variable is created.
Well, in this lecture we will review this definition together with some examples.
In ECMAScript, let and const are block-scoped variable declarations introduced in ES6.
Do you recall before you started this course I showed you the formal definition of LET and CONST as per ECMAScript? Here it is:
let and const declarations define variables that are scoped to the running execution context's LexicalEnvironment. The variables are created when their containing Environment Record is instantiated but may not be accessed in any way until the variable's LexicalBinding is evaluated. A variable defined by a LexicalBinding with an Initializer is assigned the value of its Initializer's AssignmentExpression when the LexicalBinding is evaluated, not when the variable is created. If a LexicalBinding in a let declaration does not have an Initializer the variable is assigned the value undefined when the LexicalBinding is evaluated.
In this lecture we will run over this definition using examples.
If you attempt to redeclare a variable declared with let in the same scope, JavaScript will throw a SyntaxError.
In this lecture, you will find out why this is the case.
Last but by no means least, I want to look at ECMAScript's definition of block scoped variables. To remind you, here it is:
When a Block or CaseBlock is evaluated a new Declarative Environment Record is created and bindings for each block scoped variable, constant, function, or class declared in the block are instantiated in the Environment Record.
Pictures speak more than a thousand words, so in this lecture I want to show you an example of what happens when we define variables within a BLOCK, using VAR and LET.
For the first time in this course, you'll see that now the LexicalEnvironment and VariableEnvironment point to different records. Crazy, heh?
I want to continue from the previous lecture, but this time add two console.log() statements outside of the block statement.
Congratulations on mastering the intricacies of VAR, LET, and CONST in JavaScript!
Your understanding of these variable declarations marks a significant milestone in your journey as a developer.
In this section, we also explored the concept of block scope. This knowledge not only enhances your coding skills but also prepares you for real-world applications where scope management is essential.
As you continue to apply what you've learned, remember that mastering these fundamentals will empower you to write more predictable and maintainable code.
In the next section, we will dive deeper into what "SCOPE" means in a JavaScript context.
Enjoy, and see you on the other side.
Clyde
I have received a lot of messages asking for clarification on the last question of the assignment, so I decided I'd film a lecture and walk you through it.
Enjoy.
This lecture will introduce you to some code where I ask you to think about "scoping" and give you a question. The answer may surprise you.
JavaScript implements static or lexical scoping, which means that the scope of a variable is determined by its position within the source code. This allows functions to access variables from their containing (or parent) scopes at the time of their definition, rather than at the time of their execution. Most programming languages, including Java, Python, and C, follow this lexical scoping model.
In contrast to lexical scoping, dynamic scoping determines variable scope based on the call stack at runtime. This means that a variable's value can change depending on how a function is called, rather than where it is defined.
A language that uses dynamic scoping is Perl. Another one is BASH, and I'll show you an example.
Congratulations!
You've successfully explored the concept of lexical scoping in JavaScript, and should now appreciate how JavaScript uses the [[OuterEnv]] property to reference outer parent scopes.
Its important to understand that not all languages are like this. Some support dynamic scoping (like Bash) and others support various types of scoping (like Perl).
Enjoy the upcoming questions, and I look forward to seeing you in the outro section!
I'll show you that CONST is somewhat of a misnomer.
Using const with Object.freeze() in JavaScript ensures true immutability by preventing reassignment and modification of object properties. The const keyword creates a read-only reference to the object, meaning the variable cannot be reassigned. Meanwhile, Object.freeze() makes the object itself immutable, disallowing any changes to its properties. Together, they enforce that both the reference and the object's structure remain unchanged, achieving a higher level of immutability in code
It may surprise you to see some valid use cases for VAR. What do you think?
Buckle up, and prepare for your landing!
This is a quick test that will prove how far you've come from when you first started this course, to where you are now!
Well done on completing this course. I'm super proud of you and appreciate you so much. KEEP CODING and i'll see you soon.
OpenCourser helps millions of learners each year. People visit us to learn workspace skills, ace their exams, and nurture their curiosity.
Our extensive catalog contains over 50,000 courses and twice as many books. Browse by search, by topic, or even by career interests. We'll match you to the right resources quickly.
Find this site helpful? Tell a friend about us.
We're supported by our community of learners. When you purchase or subscribe to courses and programs or purchase books, we may earn a commission from our partners.
Your purchases help us maintain our catalog and keep our servers humming without ads.
Thank you for supporting OpenCourser.