ES6/ ES2015

Arrow Functions: Lexical ‘this’ keyword

round mirror behind potted flower on floor inside room

Maybe the biggest advantage of using arrow function is that they share the surrounding this keyword, this means unlike normal functions, arrow functions don’t get their own ‘this’ keyword.

Again,

Arrow functions don’t have ‘this’ keyword, they simply use the ‘this’ keyword of the function they are written in.

So we say, they have a lexical ‘this’ variable.

ES5

var box5 = {   
color: 'green',
position: 1,
clickMe: function() {
//attach an event handler, we want it to happen on the click
document.querySelector('.green').addEventListener('click',
function() {
var str = 'This is box number' + this.position + ' and it is
' + this.color;
alert(str);
});
}
}

box5.clickMe();

//so as soon as this method is called, the event listener will be added to the element.

What will happen if we click on the green box?

This is box number undefined and it is undefined.

Why it’s not reading the value from our object?

This is because only the method calls, the this keyword is actually pointing to the object. But in a regular function call, the this keyword will always point to the global object which in the case of browser is the window object.

This is exactly what happened here. The clickMe method is a function attached to an object, so it’s a method, and so in here we have access to the position and color using the this keyword, but the callback function we have in the event handler is not a method, is a regular function call, therefore, ‘this’ keyword here does not point to box5 object, instead, it points to the window object.

And of course, the position and color are not defined on the window object. Thus, we have undefined on both.

A common pattern to avoid this is to simply create a variable.

var box5 = {    
color: 'green',
position: 1,
clickMe: function() {
//attach an event handler, we want it to happen on the click
var self = this;
document.querySelector('.green').addEventListener('click',
function() {
var str = 'This is box number ' + self.position + ' and it
is ' + self.color;
alert(str);
});
}
}

box5.clickMe();
//This is box number 1 and it is green

So the self variable points to this. (We basically store this variable in the self variable hence we can use it in the rest of the function)

This is kind of a hack to avoid this situation as in the function call here we don’t have access to the box5 object.

Ok. Now move on the ES6. Remeber we say the arrow function share surronding this keyword? Let’s see how we can leverage on it to avoid this hack here.

ES6

const box5 = {     
color: 'green',
position: 1,
clickMe: function() {
//attach an event handler, we want it to happen on the click
document.querySelector('.green').addEventListener('click', ()={
var str = 'This is box number ' + this.position + ' and it is ' + this.color;
alert(str);
});
}
}

box5.clickMe();
//This is box number 1 and it is green

If we don’t have any argument or if we have more than one argument, we use () and then add the function body.

Ok, so now this arrow function shares the this keyword with its surrounding which is clickMe method, and we know in here the this keyword points to the object, hence in the function we can use ‘this’ keyword.

Thus, the best practice is always using arrow functions when you need to preserve the value of the ‘this’ keyword.


Another scenario is

const box66 = {     
color: 'green',
position: 1,
clickMe: () => {
//attach an event handler, we want it to happen on the click
document.querySelector('.green').addEventListener('click', ()
=> {
var str = 'This is box number ' + this.position + ' and it
is ' + this.color;
alert(str);
});
}
}

box66.clickMe();

Will we obtain the same result?
=> This is box number undefined and it is undefined

Why is that?
This is because this method here now also shares the lexical ‘this’ keyword from its surrounding. And the surrounding of it is the global context, which means this method here also no longer has its own ‘this’ keyword, which means it shares the global ‘this’ keyword, which of course points to the global object window. And now we face the same situation where we don’t have color and position defined on the window, so it become undefined.

Thus, be careful with the arrow function so we won’t lose track of what the ‘this’ keyword actually points to.


Another example

Let’s create a function constructor to create a person object.

function Person(name) {   
this.name = name;
}

Add a method to the prototype propery of the Person, so the object created through the object constructor will inherite this method. (it recieves an array of friends)

ES5

function Person(name) {   
this.name = name;
}
Person.prototype.myFriends5 = function(friends) {
var arr = friends.map(function(el) {
return this.name + ' is friends with ' + el;
});
console.log(arr);
}

var friends = ['Bob', 'Hank', 'Peter'];
new Person('John').myFriends5(friends);
// new and call the method immediately and pass friends into it.

Will this work?

(3) [" is friends with Bob", " is friends with Hank", " is friends with Peter"] 

Name is undefined. Due to the exact same reason as before.

In this method, we of course have access to the this variable and it points to the name of the person which will be John. But the thing is in here we call another function which is the anonymous function.

function(el) {         
return this.name + ' is friends with ' + el;
}

Hence in here the this keyword is not going to point to the john object but instead, it points to the global object, which is window once again. So we can use that trick again. (var self = this, basically storing the this variable in a separate variable)

But let’s use another trick.

Remember call, bind, apply allow us to define ‘this’ keyword manually and bind, create a copy of this function while actually calls it.


Thus what we can do here is to create a copy of this function with the ‘this’ variable set to this.

function(el) {         
return this.name + ' is friends with ' + el;
}

This is the function, so in this function we can create a copy of the function using bind method. We want ‘this’ keyword to be this, remember, outside the anonymous function we still have access to the this variable and it points to the new Person which is John in this case, so we pass it to the function simply be creating a new copy of a function with a manually defined this keyword.

function Person(name) {   
this.name = name;
}
Person.prototype.myFriends5 = function(friends) {
var arr = friends.map(function(el) {
return this.name + ' is friends with ' + el;
}.bind(this));
console.log(arr);
}
var friends = ['Bob', 'Hank', 'Peter'];
new Person('John').myFriends5(friends);
// (3) ["John is friends with Bob", "John is friends with Hank", "John is friends with Peter"]

In a regular function call, the ‘this’ keyword will always point to the global object(window) and when we have several functions or methods, the ‘this’ keyword gets lost. So to get around this we normally create a variable within the function block called ‘self’ that stores the ‘this’ keyword, and instead of using ‘this.position’ we use ‘self.position’.

However there is another way, and that is to bind the ‘this’ keyword to a specific function by using the bind() method which sets the value of “this” in the target function when the bound function is called.

ES6 version

Person.prototype.myFriends6 = function(friends) {         
var arr = friends.map(el => `${this.name} is friends with ${el}.`);
console.log(arr);
}

As mentioned before, this function does not have its own ‘this’ keyword, which means it shares the lexical ‘this’ keyword from its surrounding which in this case is this methods where ‘this’ points to the instance.

new Person('Mike').myFriends6(friends); 

// (3) ["Mike is friends with Bob.", "Mike is friends with Hank.", "Mike is friends with Peter."]
Standard
ES6/ ES2015

Arrow Functions: basics

books on desk

Suppose that we have an array,

(remember that if want a value that won’t change overtime, we will declare the variable with const)

const years = [1990, 1965, 1982, 1937]; 

ES5
We will use map method that accepts a callback and write our code inside that callback. Remember in the map method we have access to current element, index and the array. The value returned will be stored in the ages5 array.

The value returned will be stored in the ages5 array.

var ages5 = years.map(function(el) {   
return 2016 - el;
});
console.log(ages5)

//(4) [26, 51, 34, 79]

ES6
Now we can use the arrow function

const ages6 = years.map(el => 2016 - el); 

Ok, let’s break things down.

(el => ); 

Here we have the argument and the arrow operator

2016 - el 

This is that we have in the return statement in the ES5 case.

Thus, for simple callback functions like this with only 1 argument, is as simple as this.

Just argument, arrow operator, and what we have in the return statement.

const ages6 = years.map(el => 2016 - el); 
console.log(ages6);

//(4) [26, 51, 34, 79]

If we have more than one argument, we have to provide (). For example, inside the callback, now we want to access not only the current element but also the index.

ages6 = years.map((el, index) => `Age element ${index + 1} : ${2016 - el}.`); 
console.log(ages6);

// (4) ["Age element 1 : 26.", "Age element 2 : 51.", "Age element 3 : 34.", "Age element 4 : 79."]

However, if we have more than one line here, we also need to use the {} like what we do with normal functions, also the return keyword will no longer be implicit, so we need to write it out explicitly.

ages6 = years.map((el, index) => {  
const now = new Date().getFullYear();
const age = now - el;
return `Age element ${index + 1}: ${age}.`
});

console.log(ages6);
//(4) ["Age element 1: 28.", "Age element 2: 53.", "Age element 3: 36.", "Age element 4: 81."]

To conclude, there are three ways of writing arrow functions.
First is with one argument and one line of code, this is the simplest form.
Secondly, if there are two arguments or if there is no argument, then need to add ().
Thirdly, if there are more than one line of code, then need to use the {} and the return keyword at the end.

This is basically how arrow function works.

Standard
ES6/ ES2015

ES6/ ES2015 – Strings in ES6

They are big improvements on how we handle strings in ES6.

First thing first, template literals.

firstName = 'john'; 
let lastName = 'Smith';
const yearOfBirth = 1990;

function calcAge(year) {
 return 2018 - year;
}

If we want all this data together in ES5

console.log('This is ' + firstName + ' ' + lastName + ', he was born in ' + yearOfBirth + '. Today he is ' + calcAge(yearOfBirth) + ' years old.'); 

// This is john Smith, he was born in 1990. Today he is 28 years old.

This is quite annoying to be honest.

However, with ES6, we can simply use template literals to accomplish the same result.

We use backtick instead of +. This tells JavaScript that we want to use template literals.
So now we can put all of our text and variables inside of the backticks.

This tells JavaScript that we want to use template literals.
So now we can put all of our text and variables inside of the

`` 

like this

console.log(`This is ${firstName} ${lastName}.`); 

// This is john Smith.

Not only variables can be placed inside ${}, but also JavaScript expressions.

console.log(`This is ${firstName} ${lastName}. He was born in ${yearOfBirth}. Today he is ${calcAge(yearOfBirth)} years old.`); 

//This is john Smith. He was born in 1990. Today he is 28 years old.

Recap, JavaScript expression is simply a piece of code that always produce a value.


Beside template literals, they are also some new string methods in ES6.

const n = `${firstName} ${lastName}`;  console.log(n.startsWith('j')); 
console.log(n.endsWith('j'));
console.log(n.includes(' '));
console.log(firstName.repeat(3));
//how many times we want to repeat

console.log(`${firstName} `.repeat(3));

// true false true johnjohnjohn john john john
Standard
Advanced CSS & Sass

How CSS works behind the scenes: an overview

What happens to the CSS code when we load up a webpage in the browser?

Process that happens behind the scenes:

  • The browser starts to load the HTML file.
  • It takes the loaded HTML file and parses it, which means it decodes the code line by line, – From this process, the browser builds the so called Document Object Model (DOM).
    DOM basically describes the entire web document like a family tree, with parent, children and sibling elements. So this document object model is where the entire decoded HTML code is stored.

As the browser parses the HTML file, it also finds the stylesheet included in the HTML head. Therefore, it starts to load it as well.
Just like the HTML, CSS is also parsed, but the parsing of the CSS is much more complex.

During the CSS parsing phase, there are two main steps.

  • First: Conflicting CSS declarations are resolved through a process known as the cascade.
  • Second: Process final CSS values.
    Such as converting a margin defined in percentage unit to pixel. Imagine we define a left margin as 50%, but that 50% on a smart phone is different from a 50% in a large screen. That’s why this percentage and other relative units can only be calculated on an user device in the parsing phase.

After all of this is done, the final CSS is also stored in a tree-like structure called CSS Object Model (CSSOM), similar to the DOM.

Now that we have HTML as well as CSS parsed and stored, these together form the so-called Render tree.

With that, we finally have everything needed to render the page.

In order to actually render the page, the browser uses something called the visual formatting model.

This algorithm calculates and uses a bunch of stuff that we already know, such as the box model, floats, and positioning.

After the visual formatting model has done its work, the webiste is finally rendered on the screen, and the process is fininshed.

Browser -> load HTML -> Parse HTML -> Document Object Model (DOM)

When parsing HTML -> Find CSS -> Load CSS -> Parse CSS (resolve conflicting CSS declarations (cascade) and process final CSS values) -> CSS Object Model (CSSOM)

DOM & CSSOM together form the Render three -> Website rendering: the visual formatting model -> Final rendered website

Standard
未分類

JavaScript – Blocks and IFFES

Let’s look at the new way to create IFFES!

Since variables declared with let and const are block-scoped which means these variables are defined inside of a block, and from the outside of the block they are not accessible.
This is exactly what we want,
–> Data Privacy

Before ES6, we use IFFES for that, it seems that in ES6, we have a much simpler way to achieve data privacy since all we have to do is to use a block.

A block is not restricted to if statement, for or while loop, we can also create a block simply like this

{   
//your code
}

And we just created a block !

{     
  const a = 1;
  let b = 2;
}

console.log(a + b);
//Uncaught ReferenceError: a is not defined

Since these values are not accessible from outside of the block, we got an error here. This reinforces the fact that they are block-scoped, not function-scoped.

So what we have here now is exactly like an IFFE, we created some data here that is not accessible from the outside.

It’s so much easier to write like this.


ES5 version to create variables that are inaccessible from outside

(function(){   
  var c = 3;
  var b =2;
})();
console.log(c+b);

This was the old way.


What if

{     
  const a = 1;
  let b = 2;
  var c = 3;
}
console.log(c);

The answer is

3 

This is because variable declarations with var keyword it does not matter whether they are inside of a block or not since

they are function-scoped. (instead of block-scoped)

Standard
Advanced CSS & Sass

Three pillars of writing good HTML and CSS

black and brown wooden fence

There are three important and fundamental principles that we should constantly keep in mind.

  • Responsive design
  • Write maintainable and scalable code
  • Care about web performance

Responsive Web Design (RWD)

Which means to build websites that work beautifully across multiple devices.

Maintainable and scalable code

It’s important to write clean, easy-to-understand and reusable code that supports future growth, not only beneficial to yourself but also some other developers who might work with you. Thus should think about the architecture of the css, which is the way to organize the files, how to name classes and how to structure HTML.

Web performance

Means to make the website faster, and to make it smaller in size, so the user has to download less data. There are many factors affect performance, such as making less HTTP requests (meaning should include less files in our HTML document), write less code, compress code, use a CSS processor, and reduce the number of images (since they are by far the biggest in size) as well as compress images.

Standard
Web Development

APIs (Application Programming Interface)

black smartphone near tablet computer on white surface

“An Application Programming Interface (API) is a set of commands, functions, protocols and objects that programmers can use to create software or interact with an external system.
It provides developers with standard commands for performing common operations so they do not have to write the code from scratch.”

Above is a very broad definition of APIs, let’s break it down to see various parts of and API and how it works in practice.

If we take the first part, where states API is a set of commands, functions, protocols and objects that programmers can use to create software, jQuery is actually an API that provides a bunch of methods that allow us to create software more efficiently. This is a form of API that developers use to create software.

However, what people tend to mean why they talking about API are APIs that are used to interact with an external system. A common use case is for instance, we have a dating app that matches people up by the things they’ve liked on Facebook. We need the data from Facebook in order to do this, thus, we make a get request to Facebook server from our server, and Facebook will send a response back with all of that data we need in order to populate our app.
This is one of the most common ways of using APIs, which is to interact with an external source.

Nevertheless, when we are doing this, we cannot just go into somebody else’s server and make a request, we have to do it through an API, this interface determines what are the things that we can request from their server and how should we do it.

Although different websites work differently, here’s a big picture of what usually take place.

Effectively, your server is making a request via the API to somebody else’s server, and you can pass in some parameters as inputs, and their server is interacting with their database in order to grab the data you need based on your request, and your parameters. Once it has gotten the data, it will send back through the response, and you will end up with the data you wanted from their database.

Standard
ES6/ ES2015

Let & Const

brown wooden framed glass display cabinet

Let and Const are the two new ways to declare variables which will replace the var declaration that we’ve been using so far.

//ES5 
var name5 = 'Jane Smith';
var age5 = 23;
name5 = 'Jane Miller';
//we can simply mutate the variable
console.log(name5);
//Jane Miller

//ES6
//Const is for constants which means for values that we don't want to change, let is like the old var (whose value can be changed)
const name6 = 'Jane Smith';
let age6 = 23;
name6 = 'Jane Miller';
console.log(name6);

//script.js:18 Uncaught TypeError: Assignment to constant variable.

The const keyword is used to declare constants which are variables that are immutable. (cannot be changed)

In ES6, we no longer use var, we use const if we have a variable that’s not gonna change its value overtime and we use let if we want to change the value of the variable.

However, declaring variables with const and let is not the only new thing in ES6.

Variables declared using var is function scope, but variables declared wiht let and const in ES6 are block scope.

Let’s see the difference between let/ var/ const

//ES5 
function driverLicense5(passedTest) {
  if(passedTest) {
  var firstName = 'John';
  var yearOfBirth = 1990;
  console.log(firstName + ', ' + 'born in ' + yearOfBirth + ' is now officially allowed to drive a car.' );
  }
}
driverLicense5(true);

//ES6
function driverLicense6(passedTest) {
  if(passedTest) {
  let firstName = 'John';
  const yearOfBirth = 1990;
  console.log(firstName + ', ' + 'born in ' + yearOfBirth + ' is now officially allowed to drive a car.' );
  }
} driverLicense6(true);

//
John, born in 1990 is now officially allowed to drive a car. John, born in 1990 is now officially allowed to drive a car.

How about this

//ES5 
function driverLicense5(passedTest) {
  if(passedTest) {
  var firstName = 'John';
  var yearOfBirth = 1990;
  }
  console.log(firstName + ', ' + 'born in ' + yearOfBirth + ' is now officially allowed to drive a car.' );
}
driverLicense5(true);

//ES6
function driverLicense6(passedTest) {
  if(passedTest) {
  let firstName = 'John';
  const yearOfBirth = 1990;
  }
 console.log(firstName + ', ' + 'born in ' + yearOfBirth + ' is now officially allowed to drive a car.' );
} driverLicense6(true);

//
script.js:30 John, born in 1990 is now officially allowed to drive a car.
script.js:42 Uncaught ReferenceError: firstName is not defined at driverLicense6 (script.js:42) at script.js:45

For ES5, both variables will work as long as they are in the same function, however, for ES6, since variables declared with let and const are block scoped, this brings up a question, what is a block?

A block simply refers to all the code that reside in the curly braces {}

So each time when we have an if statement or a for loop, we are creating a new block, and variables declared with let and const are only valid/ accessible by code that are inside the same block. Thus if you move outside of the block, then you’ll no longer have access to them. (which is the second console.log case)

Remember that if you move console.log out of the diverLicense5 function, it will not work as well since variables declared with var are function scoped. (which means they are only accessible inside of the function, but not from the outside.)

Then what if we want to use those variables outside of the block in ES6? We’ll just do exactly what we did with functions before.
So we declare variables outside of the block, and then define it inside the function.

However,

This only works for let.

If we really want to use constant outside of the block, then we should just declare it at the outside.

//ES6  
function driverLicense6(passedTest) {
  let firstName;
  const yearOfBirth = 1990;
  if(passedTest) {
  firstName = 'John';
  }
  console.log(firstName + ', ' + 'born in ' + yearOfBirth + ' is now officially allowed to drive a car.' );
}

driverLicense6(true);

//
John, born in 1990 is now officially allowed to drive a car.

Then it will work again.
Recap, we declared firstName variable outside of the block and define its value inside the block, that’s why we can use it on the outside.

Nevertheless, this is not the end, what if we want to use a variable before declaring it?

//ES5 
function driverLicense5(passedTest) {
  if(passedTest) {
  console.log(firstName);
  var firstName = 'John';
  var yearOfBirth = 1990;
  }
  console.log(firstName + ', ' + 'born in ' + yearOfBirth + ' is now officially allowed to drive a car.' );
}
driverLicense5(true);

// undefined

Of course it’s undefined, because in the execution context, all the variables are hoisted and set to undefined, if we use it before defining it, we will get undefined.
However, in ES6 it does not work like that.

function driverLicense6(passedTest) {  
 console.log(firstName);
 let firstName;
 const yearOfBirth = 1990;
 if(passedTest) {
  firstName = 'John';
  }
console.log(firstName + ', ' + 'born in ' + yearOfBirth + ' is now officially allowed to drive a car.' );
}
driverLicense6(true);

// script.js:39 Uncaught ReferenceError: firstName is not defined at driverLicense6 (script.js:39) at script.js:49

Now we can effectively not use a variable before it was really declared, it helps to prevent some errors.
This happens because of something called the temporal-dead zone, which basically just means that the variables are actually hoisted, but we still cannot access them before they are declared. This is just a technical term, but what you need to know is that we can only use a variable after we actually declare and defined it.


One more example

let i = 23; 
for (let i = 0; i < 5; i++) {
  console.log(i);
}
console.log(i);

// 0 1 2 3 4 23

Thus assigning other value to i variable does not change the value at the first line, and again this is because these variables are block scoped, so they are actually two different variables which happened to have the same name, so it does not matter at all since they are separate variables.

var i = 23; 
for (var i = 0; i < 5; i++) {
  console.log(i);
}
console.log(i);

// 0 1 2 3 4 5

23 will be overwritten and we will have the final i from the counter variable.

( counter i: 4 + 1 = 5, thus exit the loop)

In conclusion, if you want to start using ES6, then the best practice would be to use let for variables whose value will change overtime and use const for variables that will not be reassigned, which means they will be constant throughout the code.

Standard
ES6/ ES2015

ES6 – Quick Recap

aerial photo of building near body of water

ES6/ ES2015
ES7/ ES2016
ES8/ ES2017

Above are all well-supported in all modern browsers, but no supported in older browsers.
We can use most features in production with transpiling and polyfilling (converting to ES5)

ES6 is the version that brought tons of updates and new features to the language.

Such as

  • Variables declarations with let and const (two new ways)
  • Blocks and IIFEs
  • New String Methods
  • Arrow Functions
  • Destructuring
  • New Array Methods
  • The Spread Operator
  • Rest and Default Parameters
  • Maps
  • Classes and subclasses

Advanced

  • Promises
  • Native modules (to separate our code into different files)
Standard
JavaScript

The DOM & DOM Manipulation

It’s time to talk about how can we use JavaScript in the browser to make it interact with the web page.

Technical term for that is: DOM Manipulation, which simply means use JavaScript to interact with the webpage.


What is DOM?

  • DOM stands for Document Object Model.
  • It’s a strucured representation of an HTML document.
  • The DOM is used to connect webpages to scripts like JavaScript.
  • We can say that each HTML element (such as section, a, body, img) can be represented by a box.
<body>    
  <section>
  <p>A paragraph with <a>link</a>.</p>
  <p>Another second paragraph.</p>
  </section>
  <section>
  <img src="pig.jpg">
  </section>
</body>
  • The DOM is a fully object-oriented representation, so for each HTML box (such as the body box, section box, img box), there is an object in the DOM that we can access and interact with using our JavaScript code.

JavaScript => DOM
<=
Interation/
Manipulation

They are two different things.

So far we have just used JavaScript without any interaction with the web page, we only printed value to the console. So now we are going to use some JavaScript methods with allow us to change the DOM and therefore interact with the webpage.

Noticed that we said JavaScript “methods” instead of functions?
This means they are functions attached to an object, and that object is exactly the document object.

Document Object is the object that gives us access to the DOM.

Once again, the HTML webpage content is stored in the DOM, which can then be accessed and manipulated by JavaScript.

Standard