Variables
Intro
- This tutorial explains what literals, expressions and variables are, and goes into detail about how variables work.
- It is recommended that you follow along with each section below. Paste or type the code into your own JavaScript file and view variable values and results with console logs or using the VS Code Debug sidebar.
- The example code for the entire tutorial series is at github.com/LearnByCheating/javascript-tutorial. There is a separate file or folder for each tutorial, including the To-Do List example project. The Readme file has instructions on how to run the code.
1. Literals
Literals are fixed values, not variables, that you literally provide in your script.
Examples of literals for the most common primitive data types include:
- Number literal:
7
- String literal:
"hello"
. String literals are enclosed in single or double quotes. - Boolean literals are the keywords
true
andfalse.
Examples of object literals include:
- Object literal: Curly braces create an object literal:
{}
- To add properties to it, place name-value pairs separated by commas:
{ name: 'Joey', age: 22 }
- Array literal: Square brackets create an array literal:
[]
- Place elements in it separated by commas:
['a', 'b', 'c']
Expressions
- An expression is code that resolves to a value, such as:
4 + 3
which resolves to 7. - Expressions that resolve further to a value such as 4 + 3 are not a literals.
- Primary expressions: Primary expressions are expressions that cannot be evaluated further. "Hello", 7, and true are primary expressions. They are also literals.
Variables store values:
let x = 7;
Here we created a variable named x set to the value 7.- X is a variable not a literal.
- You can provide literals or variables in your code. Your code doesn't care. It will execute either.
typeof 7;
returns 'number'. The data type of the literal 7 is number.typeof x;
returns 'number'. The data type of the variable x is also a number because x is storing the number 7.
2. Declare and initialize a variable
- Variables are containers that store values.
- Declare a variable: You declare a variable with the keywords
const
,let
orvar
. - Identifier: followed the keyword with an identifier, which is the variable name.
- Initialize the variable: Then you initialize the variable with an = followed by the value.
const x = 1;
let y = 2;
var z = 3;
- Generally you would declare and initialize a variable in one statement, but for let and var statements you can declare a variable without initializing it.
let y; // variable y is declared but its value is undefined. y = 2; // variable y is initialized with a value of 2. var z; // variable z declared but its value is undefined. z = 3; // variable z is initialized with a value of 3.
3. Let variables can change values, const variables cannot change values
- Const and let variables were introduced in 2015 with ES6. Style guides recommend using them over the var keyword.
- The difference between const and let is const variables can't change their value, but let variables can.
- Style guides recommend using const variables unless you plan on changing the value. That way it's clear in your code which variables will change and which won't.
const x = 1;
- If you try to reassign a const variable you will get an error:
x = 2;
// throws "TypeError: Assignment to constant variable".let y = 1;
- You can reassign the value of variables declared with the let keyword:
y = 2;
4. Const/let can't be redeclared in the same scope.
- Another thing you can't do with const and let variables is redeclare them in the same scope.
- With let variables you can reassign the value.
let x = 1; // initialize the x variable and assign value 1.
x = 2; // Reassign variable x value to 2.
- But if you try to declare a variable with let or const that has the same name as another variable or function in the same scope it will throw a syntax error. And you can't catch syntax errors in try/catch blocks.
let x = 1; // initialize the x variable and assign value 1.
let x = 2; // Throws SyntaxError: Identifier 'x' has already been declared
5. Hoisted
hoistMe; // Throws ReferenceError: hoistMe is not defined.
const hoistMe = 'I am undefined until you get to me.'
- Variable declarations are hoisted to the top of their scope but not initialized.
- That means all the variables declared in our current scope are visible even before we declare them, but they are not initialized with a value until you get to them.
- If you try to access the hoistMe variable before it is declared you will get a ReferenceError.
6. Let/const are block scoped
- Code blocks: Code blocks are chunks of code enclosed in curly braces.
- An if statement is a common example of a block. The body of the if statement includes one or more statements enclosed in curly braces.
- Functions, loops, and try/catch blocks are also examples of code blocks. They have one or more statements enclosed in curly braces.
- Note: Single statement if statements and arrow functions may optionally omit the curly braces, but they are still considered blocks.
- Block Scope: Let and const variables are block scoped. That means if they are declared in a block, they can only be accessed in that block. Variables declared in a block are considered local variables for that block.
- Script Scope: Variables declared in your script that are not inside a block are scoped to the script. They can be accessed anywhere in your script after line where they are declared.
Example:
myscript.js
const x = 1; if (x > 0) { const y = 2; y; // returns 2 } x; // returns 1 y; // throws ReferenceError: y is not defined
- In the above script, the x variable is declared outside of any block so it is scoped to the script.
- Inside the if statement block, we declared a variable named y. Variables declared within the block are locally scoped within that block. They cannot be accessed outside the block.
- The last line tries to access the y variable from outside the if statement block. It gets a ReferenceError.
- To set the value of a variable in an if statement, declare it outside the if statement.
let result
const score = 80;
if (score > 60) {
result = 'Pass';
else {
result = 'Fail';
}
result; // returns 'Pass'
7. Variable shadowing
- You can't declare a variable with the same name as another variable or function in the same scope:
const num = 1;
const num = 2; // SyntaxError: Identifier 'num' has already been declared
- But you can declare a variable with the same name as another variable or function if they are in different scopes. This is variable shadowing.
- Variable Shadowing is where a local variable shares the same name as a variable or function in its containing scope.
Example:
const num = 1; if (num > 0) { console.log(num); // logs 1
const num = 2; console.log(num); // logs 2 } console.log(num); // logs 1
- In the above example the num variable is declared in the script scope set to 1.
- In the if statement block another variable is declared named num and set to 2. This second num variable only exists inside the local if statement block.
- Logging num again outside the if statement block, logs the script scoped num variable value of 1.
- The style guides recommend against shadowing because it can get confusing as to which variable you are using.
8. Variables declared with var
- Prior to ES6, variables were declared with the var keyword.
- Style guides recommend not using var. You still see it in use because all the major browsers did not fully support const/let until 2016.
The main differences are:
- Var is in the global Scope:
- Variables declared with the keyword var that are not in another function are attached to the global object, which for the browser is window. This gives them a global scope.
var x = 1;
x; // returns 1
window.x; // returns 1
- Variables declared with const and let are scoped to the script. They are not attached to the global object and are not available in other script files.
let y = 2;
y; // returns 2
window.y // returns undefined.
- Var can be redeclared in the same scope:
- Variables declared with keyword var can be redeclared in the same scope.
var x = 1;
x; // returns 1
var x = 2;
x; // returns 2
- Variables declared with const or let cannot be redeclared in the same scope.
const y = 1;
const y = 2; // SyntaxError: Identifier 'y' has already been declared
- Var is function scoped:
- Variables declared with the var keyword are function scoped, not block scoped.
- So variables declared in an if statement for example, are accessible outside the block. Variables declared in a function are not.
var x = 1; // x is scoped to the global object
if (x > 0) { // declare an if block
var y = 2; // y is scoped to the global object
}
y; // returns 2
function myFunc() {
var z = 3; // z is scoped to the function
}
z; // ReferenceError: z is not defined
- Variables declared with const and let are block scoped.
- You cannot access the block scoped variables outside the block. That includes functions since the function body is a code block.
const x = 1; // x is scoped to the script file.
if (x > 0) { // declare an if block
const y = 2; // y is scoped to the if block.
}
y; // ReferenceError: y is not defined
function myFunc() {
const z = 3; // z is scoped to the function block
}
z; // ReferenceError: z is not defined
9. Global Variables
- Variables in the global scope declared without a const, let or var statement are also attached to the global object.
x = 1;
window.x; // returns 1
- Style guides recommend avoiding this.
10. Variables set to resolvable expressions
- An expression is any valid unit of code that resolves to a value.
- If you assign a variable to an expression, the variable will be set to the expression's resolved value.
- Arithmetic expressions resolve to a number:
const num = 3 + 4; num; // returns 7
- String expressions resolve to a string:
const str = 'Joey ' + 'Smith'; str; // returns 'Joey Smith'
- Logical expressions resolve to a boolean value of true or false:
const isGreater = 7 > 6; isGreater; // returns true
- Function expressions are where you assign an anonymous function to a variable.
- Most commonly done with arrow functions.
- Then you call the function by its variable name.
const double = (x) => {
const result = x * 2;
return result;
} double(10); // returns 20
- You can also set a variable to a function call, and value resolves to the function's return value.
const res = double(10); res; // returns 20;
11. Objects
Stack vs Heap memory:
Primitives are stored by value:
- The JavaScript engine manages memory. At runtime it allocates memory required, uses it, and releases it when it's no longer needed.
- There are two places where JavaScript can store data. The memory heap and stack.
- Stack memory stacks data with fixed amounts of memory for each value. The stack stores primitive data values and references to objects. Stack memory is fast and efficient but it is static.
- Heap memory is dynamic. Objects are stored in heap memory and are not assigned a fixed amount of memory. Instead, more space can be allocated as needed.
Primitives are stored by value:
- Primitive data types include strings, numbers, booleans, null, and undefined.
- Variables assigned to values that are primitive data types are stored in stack memory as values.
const x = 1; const y = 2; const z = 3 - 2; x === y; // returns false x === z; // returns true. They both store the value 1.
The above example assigns values to variables x, y and z.
When testing for equality, x and y are not equal because they have different values.
x and z are equal since they resolve to the same value, 1.
Objects are stored by reference:
- Objects (including arrays and functions) are stored in heap memory.
- Variables assigned to object values don't store the object value itself. Instead, they store a reference in stack memory to the objects memory address in heap memory.
const obj = { name: 'Joey', age: 22, married: false };
const obj2 = { name: 'Joey', age: 22, married: false };
let areEqual = (obj === obj2); // returns false
- The two objects above are stored in heap memory. The obj and obj2 variables store (in stack memory) the address for the objects in heap memory (i.e., the reference).
- At the bottom we test if the variables are equal. They are not. Even though the property values are identical, they are stored in two separate memory locations.
const objCopy = obj;
areEqual = (obj === objCopy); // returns true
- The objCopy variable above is set to the obj variable. They are both set to the same object reference value in stack memory, which points to the same object in heap memory. So they are equal.
- If you set the obj age property to 23, since obj and objCopy both point to the same object in memory, then objCopy.age will also return 23.
obj.age; // returns 22 objCopy.age // returns 22 obj.age = 23;
obj.age; // returns 23
objCopy.age; // also returns 23
12. Objects: destructuring
- Below is a variable named obj set to an object with properties for name, age, and married.
const obj = { name: 'Joey', age: 22, married: false };
- Object destructuring assigns properties of an object to individual variables.
const { name, age, married } = obj;
- Declare the variable with a const or let statement like normal but instead of following that with a single variable name, you put object literal curly braces and list the object property names that you want to assign variables to. This will create variables for each property listed and assign the values to the property values.
- The order of the property names doesn't matter.
- We now have three local variables: name, age, and married.
Object destructuring assignment with an alias:
const { name: userName, married, age } = obj;
- To assign a variable name that differs from the property name, use an alias.
- To create an alias, put a colon after the property name, followed by the variable name you want to use. Above we assigned the name property to userName.
- Now we have three variables: userName, married, and age. They hold the same values as the object property values.
13. Arrays
- As mentioned, arrays are a type of object.
const arr = ['Joey', 'Sheena', 'Johnny'];
arr.push('Judy');
- Above the arr variable is assigned to an array of names.
- If we modify the array by chaining the push method to the array variable, it will add a new element to the end of the array.
- Because an array is a type of object, the arr variable points to its location in memory. Even though we changed the array's content, it is still holds the same address in memory.
14. Arrays: destructuring
- Array destructuring also works like object destructuring.
- Except instead of curly braces we use the array literal square brackets.
- And the variable name is whatever name we want to give each item.
- Order matters. You have to list them in the same order they are in the array.
const [user1, user2, user3, user4] = arr; user1; // returns 'Joey' user2; // returns 'Sheena' user3; // returns 'Johnny' user4; // returns 'Judy'
- You can skip items you don't need to use by not including a variable name for that item.
const [user1, , user3] = arr; user1; // returns 'Joey' user3; // returns 'Johnny'
- In teh above example, the first variable, user1, is for the first item in the array. We skip the second item by adding a comma with no variable name. We assign the third item to user3. Then skip any items after that.
- We listed the unpacked variables below it, returning their values.
Conclusion
The topics in this tutorial correspond with the JavaScript CheatSheet Variables category. Make sure you understand each topic so you can refer back to the CheatSheet when working on your own projects.If you have the CheatSheet desktop app and downloaded the JavaScript CheatSheet, go through the flashcards for this category to the point where you can answer them in order and shuffled.