Category Archives: ES6

Change detection in Angular (Obviously 2.0 & greater)

Let me define first what change detection is, in simple terms any state change that needs to be propagated to UI and ice versa. Now the application state changes can happen in   following ways which apparently all are asynchronous in nature.

  • Events – Click, selection changed, keyup
  • Remote API Ajax Calls(XHR)
  • Timers – setTimeout(), setInterval()

Now for sure we know what how the application state change happens but there is still work of notifying Angular that state has changed and do the further magic. After all in the angular code we are still using Native API’s (like setTimeOut…) there are no angular specific API’s. So there is some thing called as Zone.js which does all the magic. You must have seen zone references whenever u see any error in the console window.

So what are zone and how do they work?

As one liner definition we can say that Zones are basically an execution context for asynchronous operations. Zones basically monkey patch these native methods and provide hooks for executing change detection.  As soon as we embed zone.js in our site, pretty much all methods that cause asynchronous operations are monkey-patched to run in a new zone. For example, when we call setTimeout() we actually call Zone.setTimeout().

So now we know that zones have hooks for asynchronous operation but how does it marry with angular, answer lies in to the ApplicationRef class and source code below, it simplified version of the code….

class ApplicationRef {

  changeDetectorRefs:ChangeDetectorRef[] = [];

  constructor(private zone: NgZone) {
    this.zone.onTurnDone
      .subscribe(() => this.zone.run(() => this.tick());
  }

  tick() {
    this.changeDetectorRefs
      .forEach((ref) => ref.detectChanges());
  }
}

ApplicationRef listens to NgZones onTurnDone event. Whenever this event is fired, it executes a tick() function which essentially performs change detection.

In Angular, each component has its own change detector. So in the component tree each component will have its own change detector. This allows us to control, for each component individually, how and when change detection is performed

ChnageDetection1

Let us assume that in the component tree an event has been triggered in the Child 2.1 component.  As mentioned earlier zones have hook in to these event handlers, zones execute the given handler and notify Angular when it is done, which eventually causes Angular to perform change detection. Now for angular change detection always flows from top to bottom. Change detection is also always performed from top to bottom for every single component, every single time, starting from the root component

ChnageDetection2ChnageDetection3ChnageDetection4

This is much more predictable change detection than in Angular JS where it used to digest loop or cycle.

CD (change detection) gets stable after a one pass, if one of our components causes any additional side effects after the first run during change detection, then angular will throw an exception.

Now that we have talked @ Change detectors in Angular but what are these Change detectors, well these are not one fit all generic classes which does the change detection for all components. Angular creates CD classes at runtime for each component, which are monomorphic, because they know exactly what the shape of the component’s model is.  Monomorphic are king of opposite of polymorphic which do not have any runt time overrides or sub types.

Angular also gives control of the change detection, if we wish to. We can tell angular to run CD only for the part of the component hierarchy tree. This can be achieved with 2 things

  • Immutable data structures
  • Observables

Lets consider optimization through Immutability first, consider the followin component

import { Component, OnInit } from '@angular/core';
import { UtilityService } from './../services/utility.service';
@Component({
  templateUrl: ''
})
export class GrandChildComponent implements OnInit {
  public greatGrandChildDetails: GreatGrandChildDetails;
  public currentDateTime : string;
  constructor(private utilService: UtilityService) {
    this.currentDateTime = this.utilService.currentDateTime.toISOString();
    this.greatGrandChildDetails = new GreatGrandChildDetails();
    this.greatGrandChildDetails.firstName = "Amol";
    this.greatGrandChildDetails.lastName = "Gote";
   }

  ngOnInit() {
  }

  changeGrandChildData(){
    this.greatGrandChildDetails.firstName = "John";
    this.greatGrandChildDetails.lastName = "Doe";
  }

}

export class GreatGrandChildDetails{
  firstName: string;
  lastName: string;
}

GrandChildComponent uses as a child component, which has an input property details. We’re passing data to that component with GrandChildComponent own greatGrandChildDetails property. greatGrandChildDetails is an object with two properties. In addition, there’s a method changeGreatGrandChildData(), which changes the first name and last name of greatGrandChildDetails, No magic going on here.
The important part is that changeGreatGrandChildData() mutates greatGrandChildDetails, by changing its first and last name property. Even though that property is going to be changed, the greatGrandChildDetails reference itself stays the same.
What happens when change detection is performed, assuming that some event causes changeGreatGrandChildData() to be executed? First, greatGrandChildDetails.firstName and greatGrandChildDetails.lastName gets changed, and then it’s passed to . ’s change detector. It now checks if the given details (greatGrandChildDetails) is still the same as before, and yes, it is (reference hasn’t changed), however, the first and last name property has changed, so Angular will perform change detection for that object nonetheless. Because objects are mutable by default in JavaScript (except for primitives), Angular has to be conservative and run change detection every single time for every component when an event happens. This is where immutable data structures come into play.

Immutable objects cannot be changed and we have to change then we have change the reference.

this.greatGrandChildDetails = Immutable.create({
              firstName: 'Amol',
              lastName: 'Gote'
            });

this.greatGrandChildDetailsNew = this.greatGrandChildDetails
                                  .set('firstName', 'John');

In the above case Immutable.create is just sample API to create Immutable, you can use any library to create immutable objects. Now when I am changing the first Name property then it is going to return a whole new reference to the object.

this.greatGrandChildDetails !=== this.greatGrandChildDetailsNew from a reference perspective both are pointing to different references. If we use immutable objects in our Angular app, all we need to do is tell Angular that a component can skip change detection, if the input has not changed, let’s look at the great-grand-child component.

Immutable-Component

We can skip entire subtrees when immutable objects are used and Angular is informed accordingly.
Immutable
ChangeDetectionStrategy.OnPush – This will inform Angular that our component only depends on its inputs and that any object that is passed to it should be considered immutable.

Now let’s talk @ Observables

Observables give us some guarantees of when a change has happened, unlike immutable objects, they don’t give us new references, instead, they fire events we can subscribe to in order to react to them.

Lets look at this example

import { Component, OnInit, ChangeDetectionStrategy, Input } from '@angular/core';
import { UtilityService } from './../services/utility.service';
@Component({
  template: '{{hitCounter}}',
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class ChildComponent implements OnInit {

  @Input() addChildItemStream:Observable;
  public hitCounter : number = 0;

  ngOnInit() {
    this.addChildItemStream.subscribe(() => {
      this.hitCounter++; 
    })
  }

}

We set the change detection strategy to OnPush, so change detection isn’t performed all the time, only when the component’s input properties change, the reference of addChildItemStream will never change, so change detection is never performed for this component’s subtree. This is a problem because the component subscribes to that stream in its ngOnInit life cycle hook and increments the counter. This is application state change and we want to have this reflected in our view. This is where ChangeDetectorRef comes to the rescue, it has an API markForCheck(), it marks the path from our component until root to be checked for the next change detection run, it simply iterates upwards and enables checks for every parent component up to the root.

import { Component, OnInit, ChangeDetectionStrategy, Input, ChangeDetectorRef } from '@angular/core';
import { UtilityService } from './../services/utility.service';
@Component({
  template: '{{hitCounter}}',
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class ChildComponent implements OnInit {

  @Input() addChildItemStream:Observable<any>;
  public hitCounter : number = 0;
  constructor(private changeDetector: ChangeDetectorRef) {

  }

  ngOnInit() {
    this.addChildItemStream.subscribe(() => {
      this.hitCounter++; // application state changed
      this.changeDetector.markForCheck();
    })
  }

}
Advertisements

JavaScript function compose + ES6 Spread , REST Operators

Below is sample for compose functions using older syntax (Minus ES6)

var add10 = function(x){
  return x + 10;
}

var multiply2 = function(x){
  return x * 2;
}

var square = function(x){
  return x*x;
}

var compose = function(){
  var funcs = arguments;
  return function(){
    var args = arguments;
    for(var count=0;count<funcs.length;count++){
      args = [funcs[count].apply(this, args)];
    }
    return args[0]
  }
}

var f = compose(add10, multiply2, square);
var result = f(10);
console.log(result);

Output is 1600

Now the same can be achieved using the ES6 Spread and REST operator

var add10 = function(x){
  return x + 10;
}

var multiply2 = function(x){
  return x * 2;
}

var square = function(x){
  return x*x;
}

var compose = function(...funcs){
  return function(...args){
    for(var count=0;count<funcs.length;count++){
      args = [funcs[count](...args)];
    }
    return args[0]
  }
}

var f = compose(add10, multiply2, square);
var result = f(10);
console.log(result);

 

REST operator – ES6 introduces the rest operator, three dots (…) that precede a named parameter. That parameter is now a rest parameter that is an Array containing the rest of the parameters, hence the name. Here is the use of REST parameters from the above e.g.

var compose = function(...funcs){
  return function(...args){
    return args[0]
  }
}

One rest parameter per function, there can only be one per function and it must be the last parameter declared in the function header. Attempting to have multiple rest parameters or putting one before other parameters will throw a SyntaxError.

Spread Operator: While rest parameters use the rest operator to combine zero or more parameters into a single array parameter, the spread operator does just the opposite. It separates an array into zero or more parameters.

The spread operator looks exactly like the rest operator. It is the same three dots (…). The only difference is that it is used in function calls and array literals instead of function parameter declarations. The spread operator should be able to replace the majority, if not all, uses of apply.

At first, using the spread operator may not seem like much of an improvement over apply, besides no longer having to specify undefined or this. However, the spread operator can be used anywhere in a function call and may be used more than once as well.

Below is the example for Spread Operator from the above compose sample

args = [funcs[count](...args)];

 

ES6 + Arrow Function + Mystery with this

We have been using arrow function for quite some time in compile languages like C#, but the same is now available in java script.

An arrow function is short hand, we can leave off the function keyword and we can leave of the return statement. Even though it kind of short hand operator, but its main purposes is to get away from nuances of this keyword in javascript. First we will cover basics around arrow function then discuss nuances around this keyword.
Consider the following example

(function () {
    'use strict'
    var getName = () => "aamol";
    console.log(typeof getName);
})();

What will be the output? It is going to be function, so essentially we are declaring a function but in a short hand way. Now if we execute that function what will be the output, it would be “aamol” 

(function () {
    'use strict'
    var getName = () => "aamol";
    console.log(getName());
})();

So again as mentioned above we can leave off the return keyword in an arrow function, whatever expression is specified over there will get returned. Here is another example of arrow function

(function () {
    'use strict'
    var getName = lastName => "aamol" + " " + lastName;
    console.log(getName("gote"));
})();

So in case if we have one argument to the function then we can leave off the parenthesis. It will output “aamol gote”. Now in case if you have more than 2 parameters then we have 2 use parenthesis. Output would be the same “aamol gote”. 

(function () {
    'use strict'
    var getName = (firstName, lastName) => firstName + " " + lastName;
    console.log(getName("aamol", "gote"));
})();

Now there would be scenarios where you will have more than single expression, then how does the arrow function look like shown below, your arrow function should return some thing.

(function () {
    'use strict'
    var getName = (firstName, lastName) => {
        if (firstName && lastName) {
            return firstName + " " + lastName;
        }
        else if (firstName && !lastName) {
            return firstName;
        }
        else if (!firstName && lastName) {
            return lastName;
        }
        else {
            return null;
        }
    }
    console.log(getName("aamol", "gote"));
})();

As discussed above real purpose of arrow functions is to handle this key word within functions, “this” has always been confusing aspect of JavaScript and in ES6 arrow functions make it easier to understand. Consider following example what would be the output?

    document.addEventListener("click", function () {
        console.log(this)
    });

Output will be “#document” in chrome browser.

Whenever we have an event handler in java script, this gets set to the element that receives the event and this caused problems in ES5 because we could not get access to the context of the function. Now consider the same example with arrow function

'use strict'
document.addEventListener("click", () => console.log(this));

Output will be “#Window” in chrome browser.

We are in the global area over here and not in the context of a function so this refers to the context of code in which we running which is window a global object. So as long as we are using arrow functions this will not be set to the element that is getting the event it is going to be set to the context in the code which are running in.

Lets consider another example,

'use strict'
var person = {
    age: 34,
    firstName: "aamol",
    lastName: "gote",
    getName: function () {
        console.log(this);
    }
}
person.getName();

What would be the output, it would be person object
{age: 34, firstName: “aamol”, lastName: “gote”}

Now we will replace getName function with arrow function

'use strict'
var person = {
    age: 34,
    firstName: "aamol",
    lastName: "gote",
    getName:  () => console.log(this)
}
person.getName();

Output over here would be window object. If we were inside the function then we would get the function context

Lets take another example

'use strict'
var person = {
    age: 34,
    firstName: "aamol",
    lastName: "gote",
    getName: function(){
        return () => console.log(this)
    }
}
person.getName()();

Now in this case getName() is returning the function, so what would be the output, it would be person object, because it getName() is function and that is the context that we are working with and because we are returning the function, so this will be set to the context of invoice object.

Another important aspect for arrow functions is related to .bind, .call and .apply. Consider following example

'use strict'
var person = {
    age: 34,
    firstName: "aamol",
    lastName: "gote",
    getName: function(){
        return () => console.log(this)
    }
}

var person2 = {
    age: 36,
    firstName: "john",
    lastName: "doe",

}
person.getName().bind(person2)();

Output will be {age: 34, firstName: “aamol”, lastName: “gote”} and not person2 object. This is very important with arrow functions you cannot bind a new object to arrow functions. Javascript engine did not even throw the error, it just ignored the bind call. So when u are working with arrow functions you will not be able to change the value of this like in traditional javascript.

Like .bind similar scenario exist for .call and .apply.

'use strict'
var person = {
    age: 34,
    firstName: "aamol",
    lastName: "gote",
    getName: function(){
        return () => console.log(this)
    }
}

var person2 = {
    age: 36,
    firstName: "john",
    lastName: "doe",

}
person.getName().call(person2);

Output will be {age: 34, firstName: “aamol”, lastName: “gote”} and not person2

Same applies to .apply.

So in summary in case of arrow function .call, .bind and .apply are useless, you cannot change the value of this.

One more quirk to the arrow functions consider the following example

'use strict'
var person = {
    age: 34,
    firstName: "aamol",
    lastName: "gote",
    getName: () 
        => console.log(this)
    
}
person.getName();

This is gives an syntax error “Uncaught SyntaxError: Unexpected token =>”
New line character is problem with arrow functions you cannot put the arrow symbol on to the new line.

Arrow functions do not have “prototype” property.

'use strict'
var getName = () => "aamol";
console.log(getName.hasOwnProperty("prototype"));

Output would be false.

Whenever you declare a function in javascript it will by default have the prototype property. So unlike ES% in ES6 if you declare an function with arrow symbol, we do not have access to prototype.