Saturday, March 4, 2017

Spread and Rest

If we have to combine arrays, spread could come in handy.

const pizzas=["A","B","C"];
const special=["F","G","H"];

If we had to put "D" and "E" between those, we'd have to perform several concat() functions.
With spread, this becomes easy

const combined=[...pizzas,"D","E",...special]; //voila!

Spread takes the elements of an array and separately places those elements where the array was, i.e, inside the container!

Rest is the opposite of spread. While spread unpacks items in a container, rest can pack items into a variable. This can come in handy when we are using the arguments of an array and we want to address only say, the first two arguments first and then deal with the remaining 13 later.

sumJustTwo(12,51,16,27,515);

function sumJustTwo(a,b,...otherNumbers){
console.log("The sum of first two arguments is ",a+b);
}

ES6 Array: From, of, find and findIndex

Array.from - turns array-ish things into arrays
Array.of - creates arrays from arguments
These 2 are not on the prototype, they are a part of the Array class itself.

Array.from might be useful if we need to use something like a map function on a nodelist
We know that document.querySelectorAll(); returns a nodelist and not an array.
Thus, it is array-ish.

Array.from takes in a second argument which gives us the ability to map over that array
const peopleArray = Array.from(people, person=>person.textContent);

Another case would be if we have a function like 
sumAll(1,2,3,4,5,5,63,2,4,39);
We can handle its arguments like 
function sumAll(){
const nums=Array.from(arguments);
}
and then perform a reduce on it like
const total= nums.reduce((prev,next)=>{return prev+next;},0)

posts.find(post=> post.code===code);//returns the entry itself
posts.findIndex(post=> post.code===code);//returns the array's index # of the first entry that satisfies the condition


const doSomeSatisfy = ages.some(age=>age>10);
const doAllSatisty = ages.every(age=>age>10);




Sunday, February 26, 2017

ES6 - For Of Loop

Types of loops:

Regular for loop
for(let i=0; i<array.length; i++){}

For each loop
array.forEach(cut=>{console.log(cut);});
//can’t use break or continue over forEach

For in loop
for(const item in array){console.log(item);}
//iterates over added prototype functions too

for of (Does not work on objects)
for (const item of array){console.log(item);}
//does not iterate over added prototypes
//break and continue works too
//works on nodelists

Friday, February 24, 2017

ES6: Destructing

Destructuring allows us to access properties of an object and save them in variables all at once

const person={first:”A”,second:”B”,third:”C”};
To save these values, we would have had to write something like
function saveValues(){
const first=person.first;
const second=person.second;
const third=person.third;
}

const {first,second,third} = person;

console.log(first,second,third); //gives us A B C

We can rename the containers of values retrieved from objects or arrays too
const {first:one,second:two,third:three}=person;

We can also assign default values

const {first:one=“A”,second:two=“A”,third:three=“C”}=person;

Saturday, February 11, 2017

ES6 Arrow Functions - 'this'


‘this’ - Determines when you must use an arrow function
A normal anonymous function identifies the calling element as ’this’
But an arrow function inherits ‘this’ from its parent.

element.addEventListener(‘click’, function(){
  console.log(this);//‘this’ is element here
  setTimeout(function(){
    console.log(this) //‘this’ is ‘window’ here because the current function we are in is not bound to
    //any scope 
    //(unlike the previous function which was bound to element’s click event).
    },200);
}); 

Solution, use arrow function inside setTimeout.

element.addEventListener(‘click’, function(){
  console.log(this);//‘this’ is element here
  setTimeout(()=>{
    console.log(this) //‘this’ is still ‘element’ here because the current function we are in inherits ‘this’ 
    //from its parent 
    //our arrow function is bound to ‘element’, making ‘this’ equal to element.
},200);
}); 

If we are calling an unbounded function statement inside a bounded scope of a parent function, it goes out into global scope. We can use arrow function to preserve the value of ‘this’ instead of jumping out in the unbounded global scope.

element.classList.contains(‘classname’); //contains can be used to check for a class

*Functions that are not bound to any element, like setTimeout, have 'this' set to window.
*Arrow functions inherit 'this' from their lexical parent 



Thursday, February 9, 2017

ES6 Arrow Functions - 1

MAP applies a function to every array element and returns a new array

const names=[‘john’,’katy perry’];
const fullNames=names.map(function(name){return `${name} Mayer`;});

//using an arrow function (concise)
const fullNames2=names.map((name)=>{return `${name} Mayer`;});

//If one parameter, can omit parantheses
const fullNames3=names.map(name=>{return `${name} Mayer`;})

//If no parameters, use empty brackets ()
const fullNames5=names.map(()=>`cool Mayer`);

//If returning, can omit braces (Implicit return)
const fullNames4=names.map(name=>`${name} Mayer`);

//If returning an object expression, wrap object in ()
const race=“100m Dash”;
const winners=names.map(winner=>({name:winner, race}));

//two parameters
const winners=names.map((winner,i)=>({name:winner,position:i+1,race}));

//Arrow functions are anonymous, cannot be stack traced

FILTER returns an array of terms that result in an expression to true

const ages=[11,54,45,34,65,72,23,17];
const young=ages.filter(function(age){return age<18});

//with arrow function

const young2=ages.filter(age=>age<18);

Tuesday, February 7, 2017

ES6 Variables - 4

var is hoisted.
console.log(pizza);
var pizza=“macaroni”;// produces undefined

const and let are not hoisted.
console.log(pizza);
const pizza=“macaroni”;// undeclared variable error

*var is hoisted, let and const are not.
*Everytime a variable is accessed inside an execution context, if it is not there, its outer lexical value is used.
__

Extra: The Scope Chain 

1.Accessing a global variable locally
var a=10;
function b(){
console.log(a);
}
b();
//prints 10.
//because a exists globally

2.Accessing a local variable globally
function c(){var d=10;}
undefined
d;
//undeclared error.
//this is because function c's variable environment does not exist at a global level

3.Accessing a variable of lexical parent
function p(){var g=30; function q(){console.log(g)}; q();}
p(); //prints 30
//because g exists in the outer environment of function q, which is function p

4.Accessing a variable of lexical grandparent
function p(){var g=30; function q(){function r(){console.log(g);} r();}q();}
p();//prints 30
//because g is 30 in r's grandparent p and r's parent q does not have a value for g

5.Accessing a variable of parent despite having a grandparent 
function p(){var g=30; function q(){g=50;function r(){console.log(g);} r();}q();}
p();//prints 50
//because here, r's parent q has a value for g

If you assign a value to a variable that has not been declared, it will automatically become a GLOBAL variable given that the function is run and the assignment has been executed..

function a(){b=20;}
a(); //Gives undeclared error if a() is not run.
console.log(b);//prints 20

The Order of Execution:
-Whenever a function is come across, dive into its execution stack
-Every execution context has its own variable environment
-Each child can access its lexical parents' or lexical grandparents' or lexical great-grandparents' and so on's variables if they are not overwritten.
All of the above runs in the javascript engine
-But asynchronous events are handled by a different component of the browser
-When an event is fired, it get's placed on the event queue, which is attended to by the JS engine after its execution stack and global stack are empty.
-By FIFO service, each event is taken and an execution context for that function is created and executed..

function a(){
//I tried using setTimeout here, but setTimeout is an event not a pure function.
  var ms=3000+new Date().getTime();
  while (new Date<ms){}
  console.log("I made you wait 3 seconds. Ha ha");
}
document.addEventListener('click',function(){console.log("I was clicked!");});
a();
//Output:
//I made you wait 3 seconds. Ha ha
//I was clicked!

*Dive into execution stacks first
*Each stack has its own variable environment (inherits from lexical parents, variables are hoisted within the variable environments)
*Asynchronous events are executed in FIFO after pure JS execution stack is clear