Advanced Javascript & ES6

by Surendra Singhi

CEO & Founder at Kreeti Technologies

Special Thanks to Nabarun Banerjee for helping in making the slides.

Functional Programing Paradigm

A style of building the structure and elements of computer programs—that treats computation as the evaluation of mathematical functions and avoids changing-state and mutable data.

In mathematics, a function is a relation between a set of inputs and a set of permissible outputs with the property that each input is related to exactly one output.

Side effect

A function or expression is said to have a side effect if it modifies some state or has an observable interaction with calling functions or the outside world.

For example, this function has no side effects. Its result depends only on its input arguments, and nothing about the state of the program or its environment changes when it is called:


              int square(int x) { return x * x; }
          

In contrast, calling these functions will give you different results depending upon the order in which you call them, because they change something about the state of the computer:


int n = 0;
int next_n() { return n++; }
void set_n(int newN) { n = newN; }
          

Pure function

In programming, a function may be considered a pure function if both of the following statements about the function hold:

  • The function always evaluates the same result value given the same argument value(s). The function result value cannot depend on any hidden information or state that may change while program execution proceeds or between different executions of the program, nor can it depend on any external input from I/O devices.
  • Evaluation of the result does not cause any semantically observable side effect or output, such as mutation of mutable objects or output to I/O devices.

var values = { a: 1 };

function pureFunction ( a ) {
  var b = 2;
  a = a * b + 2;

  return a;
}

var c = pureFunction( values.a );
// `values.a` has not been modified, it's still 1
            

Higher-order functions

Functions that operate on other functions, either by taking them as arguments or by returning them, are called higher-order functions.
These allow us to abstract over actions, not just values.


function greaterThan(n) {
  return function(m) { return m > n; };
}

var greaterThan10 = greaterThan(10);
console.log(greaterThan10(11));
// → true
          

var items = [
{ name: 'Edward', value: 21 },
{ name: 'Sharpe', value: 37 },
{ name: 'And', value: 45 },
{ name: 'The', value: -12 },
{ name: 'Magnetic' },
{ name: 'Zeros', value: 37 }
];

// sort by value
items.sort(function (a, b) { return a.value > b.value; });
          

Anonymous function

An anonymous function is a function definition that is not bound to an identifier.

Normal function definition:


function hello() {
 alert('Hello world');
}

hello();
          

Anonymous function definition:


var anon = function() {
 alert('I am anonymous');
};

anon();
          

this in JS

Global context

In the global execution context (outside of any function), this refers to the global object


console.log(this.document === document); // true

// In web browsers, the window object is also the global object:
console.log(this === window); // true

this.a = 37;
console.log(window.a); // 37
          
Function context - Simple call

Inside a function, the value of this depends on how the function is called. In this case, the value of this is not set by the call. The value of this must always be an object so it defaults to the global object.


function f1() { return this; }
f1() === window; // global object
          

this continued..

Object method

When a function is called as a method of an object, its this is set to the object the method is called on. In the following example, when o.f() is invoked, inside the function this is bound to the o object.


var o = {
  prop: 37,
  f: function() { return this.prop; }
};
console.log(o.f()); // logs 37
          

this continued..

As a constructor

When a function is used as a constructor (with the new keyword), its this is bound to the new object being constructed.


function C() {
  this.a = 37;

// If the function has a return statement that returns an object,
// that object will be the result of the |new| expression.
// Otherwise, the result of the expression is the object currently
// bound to |this| (i.e., the common case most usually seen).
}

var o = new C();
console.log(o.a); // logs 37
          
call versus apply

The value of this keyword can be explicitly bound to a particular object during a function call by using the call or apply methods that all functions inherit from Function.prototype.


function add(c, d) {
 return this.a + this.b + c + d;
}

var o = {a: 1, b: 3};

// The first parameter is the object to use as
// 'this', subsequent parameters are passed as
// arguments in the function call
add.call(o, 5, 7); // 1 + 3 + 5 + 7 = 16

// The first parameter is the object to use as
// 'this', the second is an array whose
// members are used as the arguments in the function call
add.apply(o, [10, 20]); // 1 + 3 + 10 + 20 = 34
          
Function.prototype.bind

Calling f.bind(someObject) creates a new function with the same body and scope as f, but where this occurs in the original function, in the new function it is permanently bound to the first argument of bind, regardless of how the function is being used.


function f() {
  return this.a;
}

var g = f.bind({ a: "azerty" });
console.log(g()); // azerty

var o = { a:37, f:f, g:g };
console.log(o.f(), o.g()); // 37, azerty
          

Some Array Functions

Array.prototype.forEach

arr.forEach(callback[, thisArg])
          

callback: Function to execute for each element.
thisArg: Optional. Value to use as this when executing callback.


var a = ["a", "b", "c"];
a.forEach(function(entry) {
  console.log(entry);
});
          
Array.prototype.map

The map() method creates a new array with the results of calling a provided function on every element in this array. map calls a provided callback function once for each element in an array, in order, and constructs a new array from the results


var numbers = [1, 4, 9];
var roots = numbers.map(Math.sqrt);
// roots is now [1, 2, 3], numbers is still [1, 4, 9]
          

var kvArray = [{key: 1, value: 10}, {key: 2, value: 20}, {key: 3, value: 30}];

var reformattedArray = kvArray.map(function(obj){
  var rObj = {};
  rObj[obj.key] = obj.value;
  return rObj;
});

// reformattedArray is now [{1: 10}, {2: 20}, {3: 30}],
// kvArray is still [{key: 1, value: 10}, {key: 2, value: 20}, {key: 3, value: 30}]
          
Array.prototype.reduce

The reduce() method applies a function against an accumulator and each value of the array (from left-to-right) to reduce it to a single value.


[0, 1, 2, 3, 4].reduce(function(previousValue, currentValue, currentIndex, array) {
  return previousValue + currentValue;
});
          
  previousValue currentValue currentIndex array return value
first call 0 1 1 [0, 1, 2, 3, 4] 1
second call 1 2 2 [0, 1, 2, 3, 4] 3
third call 3 3 3 [0, 1, 2, 3, 4] 6
fourth call 6 4 4 [0, 1, 2, 3, 4] 10

=> Arrow functions

An arrow function expression has a shorter syntax compared to function expressions and lexically binds the this value


(param1, param2, …, paramN) => { statements }
(param1, param2, …, paramN) => expression
// equivalent to:  => { return expression; }

// Parentheses are optional when there's only one parameter:
(singleParam) => { statements }
singleParam => { statements }

// A function with no parameters requires parentheses:
() => { statements }
          

=> Arrow functions contd...


var numbers = [1, 4, 9];
var doubled = numbers.map(x => 2 * x);
// doubled is now [2, 8, 18], numbers is still [1, 4, 9]
          

var kvArray = [{key:1, value:10}, {key:2, value:20}, {key:3, value: 30}];

var reformattedArray = kvArray.map((obj) => {
  var rObj = {};
  rObj[obj.key] = obj.value;
  return rObj;
});

// reformattedArray is now [{1: 10}, {2: 20}, {3: 30}],
// kvArray is still [{key: 1, value: 10}, {key: 2, value: 20}, {key: 3, value: 30}]
          
Prototype based programing using JS

JavaScript is an object-based language based on prototypes, rather than being class-based.

JavaScript only has objects. A prototype-based language has the notion of a prototypical object, an object used as a template from which to get the initial properties for a new object. Any object can specify its own properties, either when you create it or at run time. In addition, any object can be associated as the prototype for another object, allowing the second object to share the first object's properties.

Prototype chain

JavaScript objects are dynamic bags of properties (referred to as own properties). JavaScript objects have a link to a prototype object. When trying to access a property of an object, the property will not only be sought on the object but on the prototype of the object, the prototype of the prototype, and so on until either a property with a matching name is found or the end of the prototype chain is reached.


var o = {a: 1};

// The newly created object o has Object.prototype as its
// [[Prototype]]. o has no own property named 'hasOwnProperty'
// hasOwnProperty is an own property of Object.prototype.
// So o inherits hasOwnProperty from Object.prototype
// Object.prototype has null as its prototype.
// o ---> Object.prototype ---> null

var a = ["yo", "whadup", "?"];

// Arrays inherit from Array.prototype
// (which has methods like indexOf, forEach, etc.)
// The prototype chain looks like:
// a ---> Array.prototype ---> Object.prototype ---> null

function f(){
  return 2;
}

// Functions inherit from Function.prototype
// (which has methods like call, bind, etc.)
// f ---> Function.prototype ---> Object.prototype ---> null
          
Creating Object Hierarchy in JS

function Employee() {
  this.name = "";
  this.dept = "general";
}

function Manager() {
  Employee.call(this);
  this.reports = [];
}

Manager.prototype = Object.create(Employee.prototype);

function WorkerBee() {
  Employee.call(this);
  this.projects = [];
}

WorkerBee.prototype = Object.create(Employee.prototype);

function SalesPerson() {
  WorkerBee.call(this);
  this.dept = "sales";
  this.quota = 100;
}

SalesPerson.prototype = Object.create(WorkerBee.prototype);

function Engineer() {
  WorkerBee.call(this);
  this.dept = "engineering";
  this.machine = "";
}

Engineer.prototype = Object.create(WorkerBee.prototype);
          

Array & Object destructuring


var foo = ["one", "two", "three"];
var [one, two, three] = foo;
console.log(one); // "one"
console.log(two); // "two"
console.log(three); // "three"
          

var a, b;

[a, b] = [1, 2];
console.log(a); // 1
console.log(b); // 2
          

var o = { p: 42, q: true };
var { p, q } = o;

console.log(p); // 42
console.log(q); // true
          

var o = {p: 42, q: true};
var {p: foo, q: bar} = o;

console.log(foo); // 42
console.log(bar); // true
          

Asynchrony (computer programming)

Asynchrony, in computer programming, refers to the occurrence of events independently of the main program flow and ways to deal with such events. These may be "outside" events such as the arrival of signals, or actions instigated by a program that take place concurrently with program execution, without the program blocking to wait for results.


$("#btn_1").click(function() {
  alert("Btn 1 Clicked");
});
          

Callback

When we pass a callback function as an argument to another function, we are only passing the function definition. We are not executing the function in the parameter. In other words, we aren’t passing the function with the trailing pair of executing parenthesis () like we do when we are executing a function.


$(".fetchRecord").click(function() {
  alert("Requested to fetch record.");
});
          

Promise

Promise object is used for asynchronous computations. A Promise represents a single asynchronous operation that hasn't completed yet, but is expected in the future.


var promise = new Promise(function(resolve, reject) {
  window.setTimeout(() => { resolve(1); },
    Math.random() * 2000 + 1000);
});

promise.then(function(val) {
  console.log(val); // 1
  return val + 2;
}).then(function(val) {
  console.log(val); // 3
});
            

Promise.prototype.then

The then() method returns a Promise. It takes two arguments: callback functions for the success and failure cases of the Promise.


p.then(onFulfilled, onRejected);

p.then(function(value) {
 // fulfillment
}, function(reason) {
 // rejection
});
            

var p1 = new Promise((resolve, reject) => {
  window.setTimeout(() => { resolve(1); },
    Math.random() * 2000 + 1000);
});

p1.then((val) => {
    console.log('Promise fulfilled Async code terminated');  },
  (reason) => {
    console.log('Handle rejected promise ('+reason+') here.'); }
);

Promise.prototype.catch()

The catch() method returns a Promise and deals with rejected cases only.


var p = new Promise(function(resolve, reject) {
});

p.catch(onRejected);

p.catch(function(reason) {
 // rejection
});
            

var p1 = new Promise(function(resolve, reject) {
 resolve('Success');
});

p1.then(function(value) {
  console.log(value); // "Success!"
  throw 'oh, no!';
}).catch(function(e) {
  console.log(e); // "oh, no!"
}).then(function(){
  console.log('after a catch the chain is restored');
}, function () {
  console.log('Not fired due to the catch');
});

// The following behaves the same as above
p1.then(function(value) {
  console.log(value); // "Success!"
  return Promise.reject('oh, no!');
}).catch(function(e) {
  console.log(e); // "oh, no!"
}).then(function(){
  console.log('after a catch the chain is restored');
}, function () {
  console.log('Not fired due to the catch');
});
            

Faking Multiple inheritance (almost)


function Employee() {
  this.name = "Mr. N. C. B";
  this.dept = "general";
}

function Robot() {
  this.company = "Kreeti Technologies";
}

function Manager() {
  Employee.call(this);
  Robot.call(this);
  this.reports = [];
}

Manager.prototype = Object.create(Employee.prototype);
Object.assign(Manager.prototype, Robot.prototype);
    

Questions?

References

  • https://en.wikipedia.org/wiki/Side_effect_%28computer_science%29
  • https://en.wikipedia.org/wiki/Pure_function
  • http://eloquentjavascript.net/05_higher_order.html
  • https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Functions/Arrow_functions
  • https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this
  • https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this
  • https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Details_of_the_Object_Model
  • https://developer.mozilla.org/en-US/docs/Web/JavaScript/Inheritance_and_the_prototype_chain
  • https://en.wikipedia.org/wiki/Asynchrony_%28computer_programming%29
  • http://javascriptissexy.com/understand-javascript-callback-functions-and-use-them/

Thank You!