ES6 gives us more tools to be explicit about variables and control scope.
- know when to use
let
- know when to use
const
- know when to use
var
- declare variables in the right place and time
- values of variables don't bleed over into the wrong place
var
declaration still works withlooks out but not in
const
andlet
do not- use these new tools to be more explicit about what your variables are and where they are being used.
Q. What is a block?
while(){
// yes
}
for(...){
//yes
}
if(){
//yes
}
switch(){
case: //no
case: //no
}
switch(){
case: foo{
//yes
}
case: bar{
//yes
}
}
- LET: allows you to declare variables that are limited in scope to the block, statement, or expression on which it is used.
- CONST: they are not immutable, but the reference to the variable cannot be changed. also allows you to declare the variable within that block scope.
E.g. const cannot be reassigned
var hello = 2;
const bye = 10;
for (var i = 0; i < hello; i++) {
// because of block level scope, this creates a new
// const, and hence does not come in conflict with the const bye globally
const bye = 5;
console.log(bye);
}
console.log(bye);
E.g. let - only exist in the {} scope
for (var i = 1; i <= 5; i++){
setTimeout(function () {
console.log(i);
}, 1000)
}
for (let i = 1; i <= 5; i++){
setTimeout(function () {
console.log(i);
}, 1000)
}
For let / const, you can only declare a variable inside of its scope once. JavaScript
const key = 'abc123';
let points = 50;
let winner = false;
let points = 100;
-> The browser says points has already been declared.
Now, what if I had this?
JavaScript
const key = 'abc123';
let points = 50;
let winner = false;
if(points > 40) {
let winner = true
}
The important thing here is that these two winner variables are actually two separate variables. They have the same name, but they are both scoped differently:
let winner = false outside of the if loop is scoped to the window. let winner = true inside the if loop is scoped to the block.
We are switching to let and const in nodejs.
Don't use var unless you have a specific (scope) reason. If you want a global variable, just declare it outside of anything.
The general rules are:
let
for basic type variables: strings, numbers, booleans, etc.const
for objects and arrays.const
for basic type variables whose value you don't want to change over the course of your program.- Ex.:
const milesPerKilometer = 1.6;
ES6 anaonymous functions that have their own scope
Arrow function is a more concise syntax for writing function expressions. They utilize a new token, "=>", that looks like a fat arrow. Arrow functions are anonymous and change the way scope is calculated in JS.
How do we use it?
// ES5
var multiply = function(x, y) {
return x * y
};
// Longest syntax:
// Replace the `function` keyword with `=>`, put it on the other side.
// ES6
var multiply = (x, y) => {
return x * y
};
// Single Line Syntax:
var multiply = (x, y) => { return x * y };
// Concise Syntax: ( only if you have a single parameter )
var multiply = x => { return x * 3 };
// Implicit Return Syntax:
var multiply = x => x * 3;
// Implicit Return Syntax w/o curly braces, zero parameters:
var multiply = () => 5 * 3;
// anonymous functions
setTimeout( function(){
console.log("hello");
}, 1000 );
setTimeout( () => { console.log("hello"); }, 1000 );
setTimeout( () => console.log("hello"), 1000 );
Basic block scope
Now, Javascript looks out if you want it to, but not in.
Still basic block scope + async timing
People commonly make this error:
for (var i=0; i<5; i++) {
var link = document.createElement("a");
link.innerHTML = "Link " + i;
link.addEventListener('click', function() {
alert(i);
});
document.body.appendChild(link);
}
// or a while loop if we want to be specific about the exact scope context:
var i = 0;
while( i < 5 ){
var link = document.createElement("a");
link.innerHTML = "Link " + i;
link.addEventListener('click', function() {
alert(i);
});
document.body.appendChild(link);
i++;
}
The value of i
is not held inside the event listener function.
Use let
for (let i=0; i<5; i++) {
var link = document.createElement("a");
link.innerHTML = "Link " + i;
link.addEventListener('click', function() {
alert(i);
});
document.body.appendChild(link);
}
// while example
var i = 0;
while( i < 5 ){
let j = i;
var link = document.createElement("a");
link.innerHTML = "Link " + j;
link.addEventListener('click', function() {
alert(j);
});
document.body.appendChild(link);
i++;
}
- create a new index.js file
- copy and paste the code into the file by section
- get rid of the errors for each section
console.log
each variable value
let monkey = 6;
if( true == true ){
console.log( "monkey is:"+monkey );
}
// NOTE: Constants can be declared with uppercase or lowercase, but a common
// convention is to use all-uppercase letters.
// define MY_FAV as a constant and give it the value 7
const MY_FAV = 7;
// this will throw an error - Uncaught TypeError: Assignment to constant variable.
MY_FAV = 20;
// MY_FAV is 7
// trying to redeclare a constant throws an error - Uncaught SyntaxError: Identifier 'MY_FAV' has already been declared
const MY_FAV = 20;
// the name MY_FAV is reserved for constant above, so this will fail too
var MY_FAV = 20;
// this throws an error too
let MY_FAV = 20;
// it's important to note the nature of block scoping
if (MY_FAV === 7) {
// this is fine and creates a block scoped MY_FAV variable
// (works equally well with let to declare a block scoped non const variable)
let MY_FAV = 20;
// MY_FAV is now 20
// this gets hoisted into the global context and throws an error
var MY_FAV = 20;
}
// MY_FAV is still 7
// throws an error - Uncaught SyntaxError: Missing initializer in const declaration
const FOO;
// const also works on objects
const MY_OBJECT = {'key': 'value'};
// Attempting to overwrite the object throws an error - Uncaught TypeError: Assignment to constant variable.
MY_OBJECT = {'OTHER_KEY': 'value'};
// However, object keys are not protected,
// so the following statement is executed without problem
MY_OBJECT.key = 'otherValue';
// The same applies to arrays
const MY_ARRAY = [];
// It's possible to push items into the array
MY_ARRAY.push('A'); // ["A"]
// However, assigning a new array to the variable throws an error - Uncaught TypeError: Assignment to constant variable.
MY_ARRAY = ['B'];
// change this to hold the value of i
for (var i = 1; i <= 5; i++){
setTimeout(function () {
console.log(i);
}, 1000)
}
- use the same index.js file as above
- copy and paste all of the code into the file
- execute all the functions and
console.log
each value - do not write the console.log in the function. Capture the output in a variable and console.log that.
// ES5
var multiply = function(x, y) {
return x * y
};
// Longest syntax:
// Replace the `function` keyword with `=>`, put it on the other side.
// ES6
var multiply = (x, y) => {
return x * y
};
// Single Line Syntax:
var multiply = (x, y) => { return x * y };
// Concise Syntax: ( only if you have a single parameter )
var multiply = x => { return x * 3 };
// Implicit Return Syntax w/o parentheses:
var multiply = x => x * 3;
// Implicit Return Syntax w/o curly braces, zero parameters:
var multiply = () => 5 * 3;
// anonymous functions
setTimeout( function(){
console.log("hello");
}, 1000 );
setTimeout( () => { console.log("hello"); }, 1000 );
setTimeout( () => console.log("hello"), 1000 );