Banuprakash C
Full Stack Architect,
Co-founder Lucida Technologies Pvt Ltd.,
Corporate Trainer,
Email: banu@lucidatechnologies.com; banuprakashc@yahoo.co.in
https://www.linkedin.com/in/banu-prakash-50416019/
Softwares Required:
- Visual Studio Code.
- Chrome Web Browser
- NodeJS Latest LTS
Day 1) JS, TypeScript & NodeJS Day 2 & 3) Angular
JavaScript --> Scripting language, dynamically typed and loosely typed language, event driven
file.js ==> JavaScript engine [ECMA]
- V8 --> Google [Chrome, NodeJS]
- SpiderMonkey --> Firefox
- JavaScript VM --> Opera
- Nashorn ==> Oracle products
JS5 --> ES5 version --> ECMAScript 5
file.js
console.log("Start!!!");
setInterval(function doTask() {
console.log("timed!!!");
}, 100);
document.getElementById("btn")
.addEventListener("click", function clicked() {
console.log("clicked!!!");
});
console.log("bye!!!");
class TimerThread extends Thread {
TimerThread(CallbackQueue q, fn, time) {
..
}
run() {
while(true) {
sleep(time);
q.push(fn);
}
}
}
DOM --> Document Object Model ==> document tree in the form of Object
EventListener Thread ==> Observer Observable Design Pattern
======================================================================
ES 5 --> "var" is a keyword to declare a variable
ES 6 --> "let" can be used to declare a variable [ block level scope]
var vs let
ES 5 "var"
var g = 100; // global variable
function doTask() {
var a = 10; // scope of function
if( g > a) {
var b = 20; // hoisted to function scope
c = 50; // implicit variable is hoisted to global scope
}
console.log(g, a, b, c);
}
console.log(g, c); // g and c are global scope
doTask();
===================
ES 6 "let"
var g = 100; // global variable
function doTask() {
var a = 10; // scope of function
if( g > a) {
let b = 20; // block scope
c = 50; // implicit variable is hoisted to global scope
}
console.log(g, a, b, c); // b is not visible
}
console.log(g, c); // g and c are global scope
doTask();
function add(x, y) {
return x + y;
}
console.log(add(4,5)); // 9
--------------------------
function add(x, y) {
return
x + y;
}
console.log(add(4,5)); // undefined
var a; //undefined
undefined, number, string, boolean, object, array
OOP with JS
--> Object contains state and behaviour[actions / messages] BankingAccount balance --> state credit() --> actions debit() --> actions
--> Class / function / Type --> to declare a template for object creation
var person = new Object();
person.id = 10; // state
person.name = "Tim"; // state
person.getName = function() {
return this.name; // "this" refers to "person" --> context
}
console.log(person.getName()) // Tim
2) using Function Constructor
function Person(id, name) {
this.id = id;
this.name = name;
}
// add object behaviour
Person.prototype.getId = function() {
return this.id;
}
// add object behaviour
Person.prototype.getName = function() {
return this.name;
}
// add object behaviour
Person.prototype.setName = function(n) {
this.name = n;
}
// add function/class behavior and not not object behaviour
Person.equals = function(p1, p2) {
return p1.id === p2.id; // inside this code "this" can't be used
}
var p1 = new Person(22, "George");
var p2 = new Person(67, "Amy");
p1.getName();
p2.getName();
p2.setName("Jack");
if(Person.equals(p1, p2)) {
//
}
=================================
3) Using JSON ==> JavaScript Object Notation ==> Singleton object
key is string; value can be [number, boolean, string, object, array, function, null]
var person = {
"id": 22,
"name": "George",
"setName" : function(name) {
this.name = name;
},
"getName" : function() {
return this.name;
}
}
person.getName();
person.setName("Jack");
==================================
var fn = person.getName; // --> gives function definition but "context" is lost
fn(); // here executes on global context "window" and not "person" context
gets window.name
Solution:
var ref = person.getName.bind(person); ==> get function defintion by setting "context" as "person"
ref(); // gets person.name
===========================================
High Order Functions:
- Functions which accept function as argument
- Function return a function --> treat function as first-class members
Without HOF:
var data = [4,7,2,9,22,12];
for(i = 0; i< data.length; i++) { console.log(data[i]); }
for(i = 0; i< data.length; i++) { alert(data[i]); }
for(i = 0; i< data.length; i++) { writeToFile(data[i]); }
With HOF:
function forEach(elems, action) { for(i = 0; i< elems.length; i++) { action(elems[i]); } }
forEach(data, console.log);
forEach(data, alert);
Commonly used HOF:
- forEach
- filter
- map
- reduce
- find
function add(x,y) { return x + y; }
Arrow fn:
let add = (x,y) => { return x + y; }
OR
let add = (x,y) => x + y;
============
- Function return a function --> HOF
Pure function
function adder(x, y) { return x + y; }
console.log(adder(10,2)); console.log(adder(10,5));
HOF:
function adder(base) {
return function(no) {
return base + no;
}
}
let fiveAdder = adder(5);
console.log(fiveAdder(2)); // 7
console.log(fiveAdder(4)); // 9
memoization or memoisation is an optimization technique used primarily to speed up computer programs by storing the results of expensive function calls and returning the cached result when the same inputs occur again React.memo()
Cache Angular / React getEmployee(4) -------> RESTful Web Services ------> Database ---> result to JSON --> send JSON to client --> cache
getEmployee(5) -------> RESTful Web Services ------> Database ---> result to JSON --> send JSON to client
getEmployee(4) -------> get from cache
fibanocci(34) ==> 5702887 ==> cache
fibanocci(34) ==> 0 ms
NodeJS --> Platform with V8 JavaScript engine and Libuv libraries for Async operations [ instead of WebApi]
Where can I use NodeJS?
- Building Traditional web applications like [php / Servlet & JSP / ASP/ ...]
- Building RESTful WS / GraphQL WS like --> Spring Boot / Jersey / MVC Razor ==> return JSON / XML
- Streaming Platform ==> Netflix / Prime / Hotstar
- Realtime applications ==> ChatBot
- Building client side web application development
Building client side web application development
-
We might write code in ES6 or 7 / TypeScript / CoffeeScript /LiveScript / DART --> JS engine understands ES5 --> NodeJS platform can be used to transcompile --> JS
-
Unit Testing & E2E Testing
-
Bundling a.js, b.js, c.js, d.js
index.html <script src="a.js"></script> <script src="b.js"></script> <script src="c.js"></script> <script src="d.js"></script> <script src="e.js"></script>
Problem 1: --> n + 1 hits to Server Problem 2: --> order matters [ e depends on d, d depends on c ,,,,]
Solution: use NodeJS platform to bundle "bundle.js" index.html <script src="bundle.js"></script>
-
Minify, Uglify your code
====================
Node uses Package Manager
- manage dependencies [ using 3rd party libraries] --> download dependencies
- publish libraries
- run scripts --> NPM {default} / YARN / PNPM / RUSH ==> Maven / Gradle / PIP
npm init --y
creates package.json ==> like pom.xml
- file where "dependecies" are configured / scripts are configured
--> all team members uses same "package.json"
npm install lodash npm install jest chai -D // needed in production "dependencies": { "lodash": "^4.17.21" },
// needed only in development stage "devDependencies": { "chai": "^4.3.7", "jest": "^29.3.1" }
"node_modules" folder will have all the dependencies --> and transitive dependencies downloaded.
Other team members:
$ npm install
uses package.json and downloads
"lodash": "4.17.21" ==> exact version "lodash": "^4.17.21" ==> "4.17.21 are latest version" "lodash": "~4.17.21" ==> major version has to be "4"/ "minor" and "path" can be latest
=================
By default one file is one module ==> all are private
Module System:
- CommonJS ==> default in NodeJS
- ES 6 module system
- AMD
- System.js
- UMD
- Plain JS module system
// import a module
const http = require('http'); // gets from 'pre-loaded in NodeJS' const lodash = require('lodash'); // doesn't find "pre-loaded"; gets from 'node_modules'
const {add,subtract} = require('./lib'); // relative path to pick from project
package.json
"scripts": { "start": "node app/server.js" }
npm start
================
Unit testing in JavaScript:
- Jasmine
- Mocha
- JEST
Chai is a BDD / TDD assertion library for node and the browser that can be delightfully paired with any javascript testing framework.
const {expect} = require('chai');
const {add,subtract} = require('../app/lib');
// AAA ==> Assemble Action Assert
// test suite
describe("testing lib module", () => {
// test spec
it("testing add", () => {
let result = add(4,5);
let expected = 9;
expect(result).to.be.eq(expected);
});
// test spec
it("testing subtract", () => {
let result = subtract(10,4);
let expected = 6;
expect(result).to.be.eq(expected);
});
});
"scripts": { "start": "node app/server.js", "test": "jest" },
npm test
npm i mocha -D "test": "mocha --reporter spec"
===============================================
TypeScript
- Provide an optional type system for JavaScript
var name = "Tim"; name = 10; name = true;
With TS:
var name:string = "Tim";
name = 10; // tsc will throw an error
tsc a.ts --> a.js
- Enhance code quality and understandabilty
- catch issues at compilation time rather than runtime
Basic Types: number, string, boolean
var name:string = "Tim"; var age:number = 22;
Complex types: enum, object, array
enum Direction { NORTH : 'North', EAST: 'East' }
const direction:Direction = Direction.NORTH;
Object type:
- using type
type Person = {
name:string;
age: number
}
function addPerson(person:Person) {
...
}
addPerson({name:'Roger', age:34});
addPerson({name:'Roger'}); // error
let p:Person = {
name:'Roger', age:34
}
- interface
interface Product {
name: string;
price:number
}
--> interface is extendable [Generalization and Specialization relationship] ==> IS A
interface Mobile extends Product {
connectivity: string
}
interface Tv extends Product {
screenType:string,
screenSize:string
}
let sony:Tv = {
name:'Sony OLED',
price:189000.00,
screenType: 'OLED',
screenSize:'64inch'
}
---> interface for Realization relationship
interface Renderer {
render():void;
}
class WebRenderer implements Renderer {
// code
render():void {
// logic
}
}
class TvRenderer implements Renderer {
// code
render():void {
// logic
}
}
let render:Renderer = can refer to instance of TvRender or WebRender
"any" type and "unknown" type
let data:any = 10;
data = "test";
data = true;
let data:unknown = 10;
data = "test";
data = true;
Difference:
a.ts
function invoke(callback:any) { callback(); }
invoke("Hello!!!");
tsc a.ts ==> a.js node a.js Errors: TypeError: callback is not a function
unknown forces type checking before using:
function invoke(callback:unknown) { if(typeof callback === 'function') { callback(); } else if(typeof callback === 'string') { console.log(callback); } }
"as" for type assertion:
=====================
Promise API:
=======================
JavaScript Build tools:
- Grunt
- Gulp
- Webpack
Grunt is a JavaScript task runner, a tool used to automatically perform frequent tasks such as minification, compilation, unit testing, and linting.
Webpack ==> default build tool which comes with React, Angular, Vue ==> and other frameworks for scafollding code
md webpackexample cd webpackexample webpackexample> npm init --y
webpackexample> npm i webpack webpack-cli webpack-dev-server typescript ts-loader html-webpack-plugin -D
webpackexample> tsc --init
creates tsconfig.json
export default class Person {
private name:string;
private age:number;
public constructor(name:string, age:number) {
this.name = name;
this.age = age;
}
}
npm start npm test
Now: npm run dev or npm run prod
The HtmlWebpackPlugin simplifies creation of HTML files to serve your webpack bundles. This is especially useful for webpack bundles that include a hash in the filename which changes every compilation.
index.html
<script src="bundle.js"></script>Many bundles might be created based on project
bundle.js vendor.js [ angular] lib.js [ 3rd party]
Development mode files names contain hashing bundle@df34%334.js ==> cache bundle#fvfdf6sd.js bundle!dgdf%355.js
plugins: [new HtmlWebpackPlugin({ template:path.resolve(__dirname, "src", "index.html") })]
package.json "scripts": { "start": "webpack serve --mode development", "dev": "webpack --mode development", "prod": "webpack --mode production" }
npm start