Skip to content

Latest commit

 

History

History
336 lines (273 loc) · 8.8 KB

2.1.From var to let and const.md

File metadata and controls

336 lines (273 loc) · 8.8 KB

2.1- From var to let and const

Table of contents

Num Topic
2.1.1 let and Hoisting
2.1.2 Function declaration hoisting

There are in JS three kind of Scopes:

  • Global scope (window).
  • Function scope (all function is JS creates a function scope).
  • Blocked scope (let, const allow as to use blocked scope).

let, Hoisting and Block-level 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.

Function-level scope leads to a situation called hoisting

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/]

With the upcoming ES6, we can solve the issue by using Let and const Declarations:

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/)

Function declaration hoisting:

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"); 
};

let()

Use the let keyword to define variables inside a block-level Scope.

Don't replace let for var

'var' and 'let':

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).

Difference between 'var' and 'let':

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; 
}

let and var re-declared

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'

Creating Objects:

// ES5
var o1 = "test";
var o2 = "test2";
var o3 = { o1:o1, o2:o2 };
console.log( o3 ); // Object {o1: "test1", o2: "test2"}

eg1:

// ES6
let o1 = "test1";
let o2 = "test2";
let o3 = { o1,o2 };
console.log( o3 ); // Object {o1: "test1", o2: "test2"}

eg1:

Create var from Arrays:

// 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); 

let w/function with scope and block scope:

// 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();

Ej1: let w/function

let w/looping:

// 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

Ej2: let w/looping

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

Ej3: let w/looping

const()

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);

Ej1: const

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);

Ej2: const

Inmutability

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

Diferece bettwen: const(), Object.seal() and Object.freeze()

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

You can't assign new field nor change current fields

var obj = {
  a: 1,
  b: 2
};
Object.freeze(obj);
obj.foo = 3;
console.log(obj); // {a:1,b:2}

You can change a field and/or you can assign new field

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}

⬆ back to top