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

ES6 Variables - 3


An immediately-invoked function expression (or IIFE, pronounced "iffy") is a JavaScript programming language idiom which produces a lexical scope using JavaScript's function scoping.
Runs itself immediately.

var name=“Arjun”;
//but Window has a name attribute too.
So we use IIFE
function(){
var name=“Arjun”;
}();

Let and const don’t need IIFE
{
const name=“Arjun”; //name is block scoped
}

for loop leaks its index variable.
for(var i=0;i<10;i++)
{
console.log(i); //prints 0 through 9
}
console.log(i); //prints 10 in global scope

If we have a time sensitive function in a for loop, the results may get skewed, unless we used an IIFE.
for(var i=0;i<10;i++)
{
setTimeout(function(){console.log(i);},1000); 
}
//prints 10, 10 times because in 1 sec the counter will have already run.
//replacing var with let prints out 0-9 because it acts like an IIFE.

IIFE

IIFE executes the function like it was assigned to a variable and run. It creates a function expression for the function and executes it. 

function test(){var name="Al";};
test();
//is the same thing as
(function(){var name="Al";})();
//The only difference is that the second one is executed instantly
//and the first one is executed when its name is called

IIFE Syntax
(function(){})();//is IIFE
!function(){}(); //is IIFE and returns true
-function(){}(); //is IIFE and returns NaN
$function(){}(); //is IIFE but requires JQuery
(function(){}();) //is IIFE

*IIFE produces lexical scope
*let and const behave like IIFE
*for loop does not leak

Monday, February 6, 2017

ES6 Variables - 2


let and const cannot be declared more than once *in the same block.
So if you accidentally name two lets or const the same in the same block, it gives an error.
If you declare an existing let inside a different block, it is allowed but creates, not redefines, a new let.
const cannot be updated. 

If an object is const, the structure of the object cannot change but its properties can change.
  const person={name:”Arjun”, age:26};
  person.age=27; 
  console.log(person); //shows age 27.

If you want the properties of an object to be unchangeable:
  const arjun=Object.freeze(person);
  arjun.age=27;
  console.log(arjun);//shows age 26

let and const
*can’t be declared more than once
*const properties can change
*Object.freeze

ES6 Variables - 1


var can be updated.
They can be redefined.

var width=100;
var width=200;
doesn’t warn us. We are creating 2 variables with the same name, so the first one gets over-written.

var are ‘function scoped’.
They are only available inside the function they are created.
If they are not inside any function, they are globally scoped in window.

Because var is function scoped, it can leak out of a global if statement because there is no function. 
if(age>12){var dogYears=100;}
console.log(dogYears); //this works
let and const however, are ‘block scoped’.
They don’t leak out of {}
if(age>12){let dogYears=100;}
console.log(dogYears); //this doesn’t work
functions are also blocks. So they don’t leak out of a function.

var
*doesn’t warn us
*leaks in global


ES6

I'm starting Wes Bos' ES6 (Ecma Script) course today. It is also supposed to cover some JavaScript fundamentals.

I will be summarizing what I learned from it here.

Saturday, February 4, 2017

JS30 Challenge Day 15 - localStorage



Last but not the least, and the longest one of them all!
I have added some extra functionality to my solution in this one.

form elements have a reset method in them
this.reset();

JSON.stringify();
JSON.parse();

    localStorage.setItem('items',JSON.stringify(items));

For the clearAll function, 
I had to define items as let instead of const because I need to reset it to [] an empty array in the clearAll function.

UncheckAll was pretty straightforward.
Just remember to define the new buttons outside the form, because we have already used event delegation on the form.

An event delegation is like giving a task to a responsible parent.

If you give the task to its kids, they may not behave, so you delegate it.

JS30 Challenge Day 30 - Whack a mole


'click' event has a .isTrusted property which can check for fake clicks generated by javaScript.

random*(max-min)+min; //explained:
random always assumes a value between 0 and 1
max-min gives us the difference between the two edge values
so a decimal between 0 and 1 is multiplied times the difference, which can possibly give us a max of the difference times 1, the max possible value, or it could give us a zero.
The final + min ensures that the minimum possible value if the difference between max and min is 0, will be the min value itself. So it basically offsets the value of max-min by the value of min itself, so we get a valid number!

Friday, February 3, 2017

JS30 Challenge Day 29 - Timers


We can't use:

setInterval(seconds,{
seconds—;
});

Sometimes when the browser is not active, it might pause the setInterval function. Pauses while scrolling in IOS.

*clearInterval alwaysneeds a variable name of a setInterval to stop it.

setInterval does not run immediately.
It needs 1 sec to start.

element.textContent = display;
Note: Use textContent over innerText.
innerText is IE specific and does not cover all elements

document.title can be dynamically set in JS. This updates the title of the webpage.

Remember to clearInterval the timer at the beginning of the timer function.

If an element has a name attribute in html, it can be directly selected as document.elementName in the DOM.

EventListener’s name of the event should always be enclosed in single quotes.

Access the value of an element by element.value;

this.reset();

is used to reset a DOM element like a textbox.

JS30 Challenge Day 28 - Video Speed Controller

Here we want to calculate the height of the filled bar.

So we take a Y co-ordinate from the event.
We take the offset at which the top of the parent is.
We subtract the offset from the Y co-ordinate, which gives us just how much of the bar is to be filled, call it Y.

Next we want to calculate the height %
So we divide Y by the total height of the parent.
Y/offsetHeight gives us the decimal %

Multiply that by 100 and we get just how much % of space is to be filled by speed-bar.

After that, we need to find the number associated with that much height and use it as playback rate.
At 0 height it should be 0.4
At 100 height it should be 2.5
so we do percent*(max-min)+min

element.textContent
sets the text value of our bar.

number.toFixed(x);
displays the number with x decimal places