Num | Topic |
---|---|
2.1.1 | let and Hoisting |
2.1.2 | Function declaration hoisting |
- Global scope (window).
- Function scope (all function is JS creates a function scope).
- Blocked scope (let, const allow as to use blocked scope).
Quick refresh about variable hoisting:
Up to ES6 variables are always function-level Scoped: That's to say:
no matter where you declare your variable, these are going to be hoisted (declared) on the top of the scope/execution context.
In ECMAScript 6, let does not hoist the variable to the top of the block.
var n = 123;
(function() {
// what really happens: JS engine automatically is declared undefined: var n;
alert(n); // n is undefined: So, ‘undefined’ happens because hoisting
var n = "local"; // remove var then n is global to local-scope
})();
(ES5 undefined. Hoist variables)[http://www.es6fiddle.net/idfyd3ky/]
ES6 doesn't hoist the variables to the top of the block. If we have a reference to a variable in a block before the let this now give us a ReferenceError instead undefined
let n = 123;
(function f(){
console.log(a);
let a = 1; // a is ReferenceError
})()
(ES6 ReferenceError. No hoist variables)(http://www.es6fiddle.net/idfyclmu/)
Quick refresh about function hoisting:
Variables are automatically declared on the top of the function regardless where I have the car keyword: It is the same as include: var n = undefined;
'function statement' pattern ARE hoisted:
hoisted(); // logs "foo"
function hoisted() {
console.log("foo");
}
'function expressions' pattern are NOT hoisted:
notHoisted(); // TypeError: notHoisted is not a function
var notHoisted = function() {
console.log("bar");
};
Use the let keyword to define variables inside a block-level Scope.
Don't replace let for var
The difference is scope (the location where variables lives): The variables declared with 'var' are scoped to the function block (or global if outside a function block) while those declared with 'let' are scoped to the enclosing block (or global if outside any block) which may be smaller than the function block.
In other words: Variable declared using 'let' will only be available in the 'current blocked block', using var will be on the 'entire function'. The let keyword allows you to define variables within the scope of the block (block scoping).
Let cannot be redeclared on the same block. Let avoid hoisting. var creates hoisting. Let creates block scoping. Let defines a variable where it needed.
if (true) {
let foo;
let foo; // TypeError thrown.
}
if (true) {
var foo;
var foo2;
}
On es5var : The variable i, declared with var keyword, is hoisted and is available to the whole function. On es6let: The variable i is scoped to the for loop. It's visible just inside the parentheses and the curly braces of the loop.
function es5var(){
// i is visible here due to variable hoisting
for(var i=0; i<10; i++){
console.log(i);
// of course i is available here
}
// i is available as well
console.log(i);
}
es5var();
// ES6 using let
function es6let(){
// i is NOT visible here
for(let i=0; i<10; i++){
console.log(i);
// i IS BLOCK SCOPE to this block {}
}
// i is NOT available here
// console.log(i);
}
es6let();
Eg. difference ES5 'var' and ES6 'let'
Further examples: The main difference is that the scope of a var variable is the entire enclosing function:
function foo() {
var x = 1;
if (true) {
var x = 2; // same variable: scope of a var variable is the entire enclosing function
console.log(x); // 2
}
console.log(x); // 2
}
function foo2() {
let x = 1;
if (true) {
let x = 2; // different variable: Variables declared by let have as their scope the block in which they are defined
console.log(x); // 2
}
console.log(x); // 1
}
Eg. difference ES5 'var' and ES6 'let'
// ES5
var o1 = "test";
var o2 = "test2";
var o3 = { o1:o1, o2:o2 };
console.log( o3 ); // Object {o1: "test1", o2: "test2"}
// ES6
let o1 = "test1";
let o2 = "test2";
let o3 = { o1,o2 };
console.log( o3 ); // Object {o1: "test1", o2: "test2"}
// ES5
var c = [1,2,3];
var p = c[0];
console.log(p);
// ES6
var c = [1,2,3];
var [a1,a2,a3] = c;
console.log(1,2,3)
## Creating Arrays:
```javascript
// ES6
Array.of(1, 2, 3);
// scope
function fScope() {
if(true) {
var sun = 'here'; // sun is "hoisted" to the function block
}
console.log('sun is ' + sun); // sun is visible
}
fScope();
// block scope
// the let keyword allows you to define variables within the scope
function fBlockScoped() {
if(true) {
let sun = 'here'; // sun is NOT "hoisted" out of this block
}
console.log('sun is ' + sun); // sun is not defined
}
fBlockScoped();
// error on j2
for(var v = 0; v < 10; v++) {
// 'v' is only available within the for block
console.log(v);
//var v2 = v;
}
for(let j = 0; j < 10; j++) {
// 'j' is only available within the for block
console.log(j);
let j2 = j;
}
console.log("var -->", v);
console.log("let -->", j); // error j is not defined because of let
for (var v = 0; v < 3; v++) {
console.log('loop:', v);
}
console.log('after loop:', typeof v); // after loop: number
for (let l = 0; l < 3; l++) {
console.log('loop:', l);
}
console.warn('after loop:', typeof l); // after loop: undefined
It can be typically use when we declare a value that it is going to be "read only", or we are planning to reuse several times without changing it. We will be able to create constants and make sure its value won’t be changed.
const no = [{'here':'there'}, {'owesome':'ES6'}];
console.log(no);
// var no = [{'no':'posible'}];
console.log(no);
let x = 10;
if(true) {
let x = 20; // THIS X IS ONLY VALID IN THE BLOCK SCOPE
console.log(x); // 20
}
console.log(x); // 10
// HOW TO USE CONST
const FIXED_VALUE = 10;
console.log(FIXED_VALUE);
ES6 const does not indicate that a value is ‘constant’ or immutable, the inmutable is the const binding variable not its properties. So in fact, a const value can definitely change. The following is perfectly valid ES6 code that does not throw an exception:
const foo = {};
foo.bar = 100;
console.log(foo.bar);
If we want to make an Object inmutable we need to use:
const foo = Object.freeze({
'bar': 100
});
foo.bar = 42;
console.log(foo.bar); // 100
const()
- const and Object.freeze are two completely different things.
- const applies to bindings ("variables"). It creates an immutable binding var but you still can change the properties., i.e. you cannot assign a new value to the binding.
Object.seal() -It prevents "adding and/or removing properties" from the sealed object -Can throw a TypeError when attempting to modify (most commonly in strict mode) -Using delete will return false -It makes every property non-configurable, and they cannot be converted from data accessors to properties (and vice versa)
Object.freeze() -Exactly what Object.seal does, plus: It makes an object immutable: It prevents "changing" any existing properties
var obj = {
a: 1,
b: 2
};
Object.freeze(obj);
obj.foo = 3;
console.log(obj); // {a:1,b:2}
const obj = {
a: 1,
b: 2
};
obj.a = 13; // You can change it
obj.foo = 3;
console.log(obj); // {a: 13, b: 2, foo: 3}