Creating and Initializing Variables
Six rules decide almost every declaration question. Free to watch, with a free slide PDF and practice questions.
Chapters
- 0:00 Creating and Initializing Variables
- 0:34 Quick recap: the exam asks you to predict
- 1:11 Six rules decide almost every declaration question
- 1:55 One table holds the whole lesson
- 2:55 To initialize is to give the first value
- 3:46 Two mistakes, two different errors
- 4:34 const locks the binding, not the contents
- 5:28 let and const stay inside their block
- 6:09 var leaks out of blocks
- 6:57 Hoisting: declarations are processed first
- 7:28 Early let and const throw; early var does not
- 8:25 var can be redeclared; let and const cannot
- 9:23 A valid name has four rules
- 10:10 Declared but empty means undefined
- 10:40 Learn the error type, not the wording
- 11:24 One keyword per pattern; defaults skip null
- 12:20 Ask what the requirement protects
- 13:03 Seven terms to say in your own words
- 13:41 Write your prediction first
- 14:51 Eight questions, closed book
- 16:05 A developer runs the following code. What is the result?
- 16:49 undefined is logged, then a ReferenceError
- 17:50 Three keywords, three rules
- 18:24 Now test it, then move to values
Test yourself on creating and initializing variables
Practice questions for this lesson come with a full explanation of why each answer is right or wrong, and link back to the exact moment in the video.
Take the free diagnosticTranscript
Read the full lesson text
Creating and Initializing Variables 0:00
Welcome to module one, lesson one: creating and initializing variables. This module is called Variables, Types, and Collections, and it carries twenty three percent of the exam. That makes it one of the two heaviest domains. In this lesson we look at three keywords: var, let, and const. By the end, you will be able to read a declaration and predict three things: whether it throws, what it holds, and where it is visible. Everything in this lesson can be answered by simply reading the code.
Quick recap: the exam asks you to predict 0:34
Before we start, a quick recap from the exam overview. First, exam questions start from a scenario, a requirement, or a block of code. Second, there are seven domains, and this one is twenty three percent of the score. Third, questions come in three shapes: predict what code does, pick the right tool, or fix something broken. And fourth, our rhythm in every lesson is rule, trace, trap, proof. Today is mostly about the predict shape. If you skipped the overview, the one thing to keep is that rhythm.
Six rules decide almost every declaration question 1:11
Here is what you will learn. Six rules decide almost every declaration question on the exam. This domain is twenty three percent of the exam, which works out to about fourteen questions out of sixty. And there are twelve practice questions in the bank for this lesson. The six rules are: how to initialize a variable, how const behaves with mutation, scope, hoisting and the temporal dead zone, redeclaration, and finally why you should learn the error type rather than the message text. Rules three, four, and five produce most of the questions, so we will slow down there. We will also cover naming rules, uninitialized values, and declarations that use destructuring.
One table holds the whole lesson 1:55
This is the foundations slide, and one table holds the whole lesson. Every remaining slide is one row of this table, with an example, so pause here and read each row aloud. Scope. A var is scoped to the function, or to the global scope. Both let and const are scoped to the block. Initializer required. A var does not need one, and neither does let. A const must be initialized when it is declared. Reassign. You can reassign a var and a let. You cannot reassign a const. Redeclare in the same scope. A var can be redeclared. A let or a const throws a Syntax Error. And reading a variable before its declaration. A var gives you undefined. A let or a const throws a Reference Error. One practical rule to carry with you: M D N recommends const over let whenever the variable is never reassigned.
To initialize is to give the first value 2:55
Let's start with the core explanation. To initialize a variable is simply to give it its first value. Look at the first line, let a, with no value. That is declared but not initialized, so it holds undefined. On the second line, let b equals two initializes the variable. The next statement, b equals three, is not an initialization. It reassigns the variable, and that is allowed with let. And const pi equals three point one four is a constant, initialized in the same statement. You can declare several variables in one statement with commas, but one per line reads better. Why does this matter? Because var and let do not need an initializer. They start as undefined. Predict, then run: console dot log of a prints undefined.
Two mistakes, two different errors 3:46
Now our first exam trap. Two mistakes, two different errors. The wrong shortcut is thinking that any const mistake is a Type Error. The correct exam test is to ask when it fails. Take const x with no value. That is a Syntax Error, because the initializer is missing. The code is invalid before it ever runs. Now take const x equals one, then x equals two. The declaration is fine. The failure happens while the program is running, when you try to assign to a constant, and that is a Type Error. So if both errors appear in the options, choose by timing. Before running is a Syntax Error. While running is a Type Error. And remember, let x with no value is simply undefined, with no error at all.
const locks the binding, not the contents 4:34
Second trap: const is not immutable. It locks the binding, not the contents. The wrong shortcut says, const means the object can't change. The correct exam test asks, can the variable point somewhere new? Look at the code. We declare const user as an object with a name of Ann. Then we set user dot name to Bo. That works. The object's property changed, and the variable still points at the same object. But user equals an empty object would throw a Type Error, because that tries to point the variable at a new object. The same goes for arrays. Const list equals an empty array, then list dot push of A, is perfectly fine. Elements can be added. The variable just can't be reassigned. If the requirement says properties must not change, the practical rule is to use Object dot freeze.
let and const stay inside their block 5:28
Now scope, starting with let and const. They stay inside their block. In the code, the outer function contains a block in curly braces, holding let y equals five. If you try to read y from outside that block, you get a Reference Error. Scope is the nearest block, a function body, a switch statement, or the header of a for loop. A let declared in a for header is not visible after the loop. Inner blocks can also shadow outer variables. Shadowing means an inner variable with the same name hides the outer one inside its block. The outer variable is untouched. It is simply hidden while you are inside the inner block.
var leaks out of blocks 6:09
Here is a classic trap. A var leaks out of blocks. The wrong shortcut says curly braces always make a scope. The correct exam test asks, which keyword declared it? Trace the code. We have an if true block with var x equals five inside. After the block, console dot log of x prints five. The if block ran, x became five, and because var ignores blocks, x is still alive. A var is scoped to the function, or to the global scope in a script. A var inside a loop is visible after the loop. And a top level var in a script becomes a property of global this, while a let does not. This is the most common scope question on the exam. A var leaks. Let and const do not.
Hoisting: declarations are processed first 6:57
Time for a jargon check. Hoisting means declarations are processed first. A var is hoisted and starts as undefined. Function declarations are hoisted entirely. Here is the example. Console dot log of a, then var a equals one. The first line prints undefined, not an error. Why? Because only the declaration moves. The assignment stays right where you wrote it. So reading a before the assignment gives you undefined.
Early let and const throw; early var does not 7:28
This brings us to the most tested trap in this lesson: the temporal dead zone. The wrong shortcut says all declarations behave like var before their line. The correct exam test asks two questions: which keyword, and has the declaration run yet? In the code, console dot log of b comes before let b equals two. That throws a Reference Error. Follow the timeline. The scope starts, and from that moment until the let line runs, reading b throws. That stretch is the T D Z. Once let b equals two has run, b is safe. The practical rule: it's timing, not position. A function that uses a let variable is fine, as long as it is called after the declaration. And one more detail. Even typeof throws inside the T D Z, while typeof on a truly undeclared name just returns the string undefined.
var can be redeclared; let and const cannot 8:25
Next trap: redeclaration. A var can be redeclared. A let or a const cannot. The wrong shortcut says a var inside a nested block is a separate variable. The correct exam test asks, does it land in the same scope after hoisting? Look at the code. We declare let a equals one. Then, inside curly braces, var a equals two. That is a Syntax Error: identifier a has already been declared. The var hoists up into the enclosing scope, where the let already lives. A few more cases. Var a equals one then var a equals two is allowed. A let that reuses a function parameter's name is a Syntax Error. And in a switch statement, all cases share one block, so wrap each case's let in braces. In plain words: a let declaration cannot share the exact same block scope with any other declaration of the same name.
A valid name has four rules 9:23
Now some naming rules. A valid name has four. First, characters: letters, digits, the dollar sign, and the underscore. Second, the name can't start with a digit. Third, names are case sensitive, so apple is not the same as apple in all caps. And fourth, reserved words like let, class, and return can't be used. The usual style is camel case. Use upper case with underscores for hard coded constants whose value is known before the code runs. One more thing. Assigning to an undeclared name creates a variable in non strict code, but throws in strict mode. And on the exam, if an option starts with a digit or uses a reserved word, you can rule it out immediately.
Declared but empty means undefined 10:10
Let's cover what a variable holds when nothing has been put in it. Declared but empty means undefined. A var or a let that is declared but not initialized holds undefined. And you should know the types. ECMAScript has seven primitive types: Boolean, null, undefined, Number, BigInt, String, and Symbol. Plus Object. Notice that undefined is both a type and the value an uninitialized variable holds.
Learn the error type, not the wording 10:40
Here is a point that saves time on the exam: learn the error type, not the wording. A const with no initializer is a Syntax Error. The V8 wording is, missing initializer in const declaration. A let or a const read too early is a Reference Error. In V8, the message says, cannot access X before initialization. And a let that reuses a parameter name is a Syntax Error, with the message, identifier X has already been declared. The practical rule: Firefox and Safari word these messages differently. The type is what stays the same. Remember, the Reference Error depends on execution order, while the two Syntax Errors depend on how the code is written.
One keyword per pattern; defaults skip null 11:24
Destructuring declarations follow the same keyword rules. One keyword per pattern, and defaults skip null. Look at the first line: const, curly braces, a equals one, equals an empty object. The object has no a, so a gets its default and is one. Now the second line: const, c equals two, from an object where c is null. The default does not apply, so c is null. Binding patterns start with var, let, or const. All variables in one pattern share that keyword, so if you need one re-assignable and one read only, destructure twice. A destructuring declaration needs an initializer. And a default applies for missing or undefined values, never for null. That matters because null is a real value, so the default does not replace it. This is a favorite exam detail.
Ask what the requirement protects 12:20
Let's pull this together with a selection map. Ask what the requirement protects. If the requirement says the value is never reassigned, use const. M D N recommends const over let in that case. If the value changes later, use let, because let may be reassigned. If properties must not change, use Object dot freeze, because const blocks reassignment, not mutation. And if you need one value re-assignable and another read only from the same object, destructure twice, because all variables in one pattern share a keyword. Use this table when the question says, which declaration should the developer use. Pick the keyword from the requirement, then check scope and timing.
Seven terms to say in your own words 13:03
Seven key terms to say in your own words. An initializer is the first value in a declaration. Block scope means visible only in the nearest block. Function scope means a var is visible across its whole function. Hoisting means declarations are processed first. The temporal dead zone is the stretch where reading a let or a const throws, until its declaration runs. Shadowing means an inner name hides an outer one. And Object dot freeze blocks property changes. Pause the video now. Cover each card and explain the term aloud.
Write your prediction first 13:41
Now the proof stage, starting with a lab. Write your prediction first. You have six snippets on screen. For each one, decide what it logs, or which error it throws, and write it down before checking. Take three minutes on your own, and write down your predictions before checking. Now the answers, one snippet at a time. Snippet one prints undefined. The var is hoisted and starts as undefined, so reading it early does not throw. Snippet two throws a Reference Error. The let is still in the temporal dead zone until its declaration runs. Snippet three prints five. A var ignores blocks, so x is still alive after the if. Snippet four prints an array containing one. Const locks the binding, not the contents, so the push is allowed. Snippet five throws a Type Error, because a const cannot be reassigned. Snippet six is a Syntax Error. The var inside the block hoists into the same scope as the let, and a let cannot be redeclared there. A wrong prediction is the lesson. Go back to the slide that explains it.
Eight questions, closed book 14:51
Self check: eight questions, closed book. Answer out loud, then I will reveal each one. One. What errors do the two const snippets produce? A Syntax Error for the one with no value, then a Type Error for the reassignment. Two. What value does a hold after a let declaration with no initializer? Undefined. Three. What do the two read-before-declaration snippets print, one with var and one with let? Undefined for the var, and a Reference Error for the let. Four. Is x visible after an if block that declares it with var? Yes, because var ignores blocks. Five. Can a const array be pushed to, and can it be reassigned? Yes to the push, no to the reassignment. Six. Which redeclarations are a Syntax Error? Any let or const name redeclared in the same scope. Seven. Does a top level let create a property on global this? No. And eight. Does typeof on a let in the T D Z return undefined? No, it throws. How many did you get? Anything you missed, go back to its slide.
A developer runs the following code. What is the result? 16:05
Time for a practice question, taken from the question bank. This is a predict question. Pause the video and trace it line by line before you read the options. A developer runs the code shown. What is the result? Option A: a Reference Error is thrown on the first line. Option B: undefined is logged, then a Reference Error is thrown. Option C: undefined is logged twice. Option D: undefined is logged, then two. This question combines hoisting and the temporal dead zone, the two traps from this lesson. Trace each declaration. Which keyword, and has it run yet? Pause now, and I will give you the answer on the next slide.
undefined is logged, then a ReferenceError 16:49
The answer is B. Undefined is logged, then a Reference Error is thrown. Here is why. The var a is hoisted and starts as undefined, so the first log prints undefined. The let b is in the temporal dead zone until its declaration runs, so reading it throws a Reference Error. Now the wrong options. A says a Reference Error on the first line. That confuses var with let. A var is hoisted and initialized, so the first line does not throw. C says undefined is logged twice. That treats let like var. A let does not start as undefined. Reading it early throws. And D says undefined, then two. That would require let to be readable before its line. But the error stops the script, so the assignment of two never matters. The takeaway: ask which keyword, and has the declaration run yet? Early var is undefined. Early let throws.
Three keywords, three rules 17:50
Let's consolidate. Three keywords, three rules. Const requires an initializer. It can't be reassigned, but mutation is allowed, and Object dot freeze blocks it. Var is function scoped. It is hoisted to undefined, can be redeclared, and leaks out of blocks. And let and const are block scoped. Reading them in the T D Z gives a Reference Error, and redeclaring them is a Syntax Error. Remember: learn the error types, not the message text. If you can say these three cards from memory, you've got the lesson.
Now test it, then move to values 18:24
That completes lesson one. Now test it, then move on to values. The flow is: declare it, predict it, test it. Your practice set is questions V T C zero zero one through V T C zero one two in the bank. Do them now, closed book, and map any miss back to the slide that explains it. In the next lesson, Strings, Numbers, and Dates, we move from how a variable is declared to the values it holds. See you there.