JavaScript Tutorial
indexjavascript history javascript versions environment setup variables and data typesOperatorsstrings and numbers programming constructs arrays built in objects functions objects call apply bind closures error handling debugging CallbacksJS in Browser
BOM and DOMBrowser EventsWeb APIAjaxJQueryMost popular librariesAdvanced
prototypes Object Oriented ProgrammingModulesAsynchronous programmingBinary DataInternationalizationreactangularjsProjectsMiscellaneous
typescriptJS ecosystemChrome dev toolstesting frameworksInterview questions and AnswersObject oriented programming in javascript
Construction functions
Befor class keyword was introduced in ES6, below syntax was being used to achieve the inheritance. class keyword is a syntactic sugar.
//constructor function
function F1(id,name){
this.id=id;
this.name = name;
}
//m1 is prototype method meaning all objects created by new F1() will inherit it
F1.prototype.m1 = function(){
console.log(this.name + " name ")
}
let o1 = new F1(1,"sabgar")
//we are able to call m1 due to prototypical inheritance
o1.m1()
o1 instanceof F1
class and constructor keyword (es6) - Syntactic sugar for Constructor Functions
As you can see, we can create classes in JS using "class" and "constructor" keywords. But this is just a syntactic sugar for function F1.
//class
//F1 is actually transformed into a function by interpreter/compiler
class F1{
constructor(id,name){
this.id = id
this.name = name
}
/*
- add # to the variable to make it private
- private method still in progress
*/
//m1 is added to prototype of function F1.
m1() {
console.log(this.name + " name ")
}
}
let o1 = new F1(1,"sss")
o1.m1()
Extending classes (Inheritance) and polymorphism in JS
- inherited objects not copied unlike Java
- Inheritance is achieved through prototypes
- Only functions have prototype e.g. Array is a function that has a prototype where all array methods are stored.
class Car {
constructor(make,model){
this.make = make
this.model = model
}
getCarMake(){
return this.make
}
}
class ElectricCar extends Car{
//add extra props here
constructor(make,model,batteryCapacity){
super(make,model)
this.batteryCapacity = batteryCapacity
}
//method overriding
getCarMake(){
return "Electric car by " + this.make
}
//method overloading
getCarMake(x){
return "Electric car by " + this.make + this.model
}
}
let teslaModelY = new ElectricCar("Tesla","Model Y", "2000")
console.log(teslaModelY.__proto__)
Car.prototype.isPrototypeOf(teslaModelY) //returns true
//teslaModelY.__proto__.__proto__ -> here is inherited method (Car prototype method)
//just follow chain to find the method
this binding
//binding using new keyword
function F1(id,name){
this.id=id;
this.name = name;
}
//implicit binding
let person = {
name : "sdsd",
hi(){
console.log(this.name)
}
}
//explicit binding
let person = {
name : "sdsd",
hi: function (){
console.log(this.setTimeOut)
}.bind(window)
}
//Arrow functions - lexical binding
let person = {
name : "sdsd",
hi(){
let inner = () => {
//this refers to person due to lexical scope binding
console.log(this.name)
}
inner()
}
}
/*
this refers the object that invoked the function
in global context, it is window/global object
in arrow functions, this refers to the global object
same function can be called by different object and this can be used to
change the behaviour of function based on object.
arrow functions are lexically bound to surrounding object
In named functions, this refers to the global object unless function is called
by an object
this keyword is dynamically scoped. it does not matter if it is wrapped in a
object. what matters is how/which object called the function
*/
let o1 = {
f1(){
//this refers to object o1
console.log("f1", this)
function f2(){
//this refers to window object as f2 was not called by o1
console.log("f2", this)
}
f2()
}
}
o1.f1();
let o1 = {
f1(){
//this refers to object o1
console.log("f1", this)
let f2 = () => {
//this refers to o1 as f2 is arrow function and f2 is called by the
// function which was in turn called by o1. So it looks for nearest
//object that called the function using scope chain
console.log("f2", this)
}
f2()
}
}
o1.f1();
//above can be also achieved by using bind - old way
let o1 = {
f1(){
//this refers to object o1
console.log("f1", this)
let f2 = function() {
//this refers to window object as f2 was not called by o1
console.log("f2", this)
}
//bind o1 to f2. if you do not bind, this will refer to window object
// inside f2 function
f2.bind(this)()
}
}
o1.f1();
Web development and Automation testing
solutions delivered!!