Javascript : OOP

Javascript : OOP

Fifth article on my javascript exploration and I explain here the differences between javascript and and other regular Object Oriented Programming languages. ES6 made it easier but it is important to understand how inheritance is adressed in js.

Prototype

Javascript is a prototype-based OOP. Unlike other programming languages, classes do not exist in javascript (even the class keyword introduced further below is not a class per say). Instead, everything is an object.

In JS, all functions include a prototype object by default, which is a special type of enumerable object to which properties can be attached. These properties will be shared across all the instances of its constructor function.

// This is the legacy way of creating 'classes' in javascript
function Person() {
    // The body of this function is called the 'constructor function'.
    
    // 'this' is valid in a function. It adds the following properties to 
    // the 'prototype' of the object and they'll be shared with all instances
    this.name = 'Mike';
    this.gender = 'Male';
}

// You can add new properties to 'Person'
Person.prototype.age = 41;

// Internally, 'mike' has a `__proto__` property that points to the 'prototype' object
// of 'Person'. Note that instances, do not have the 'prototype' property (it is invisible).
var mike = new Person();
console.log(mike.age); // 41

// To access 'prototype' from an instance, use the following
let proto = Object.getPrototypeOf(mike); // returns 'Person's prototype object

// 'prototype' has a property named 'constructor' which points to Person() method
console.log(proto.constructor);

Any change made to the prototype only reflects in new instances. Old instances keep a reference to the old prototype.

var mike = new Person();
Person.prototype = { name: 'Jody', gender: 'Female' };
var jody = new Person();

console.log(mike.name); // 'Mike'
console.log(jody.name); // 'Jody'

You can attach new functions and properties to an instance (this is how javascript handles inheritance). Then when calling a function or property, the javascript engine looks it up into the prototype of the instance first and escalates to parents' prototype until finding it.

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

// we create an 'Employee' class
// inheriting 'Person'
function Employee(name, gender, position) {
    // call Person's constructor in this context
    Person.call(this, name, gender);
    this.position = position;
}
// build inheritance
Employee.prototype = new Person();
Employee.prototype.constructor = Person;

let employee = new Employee('Mark', 'Male', 'Architect');

console.log(employee instanceof Person); // true
console.log(employee instanceof Employee); // true

Classes

Introduced with ES6, class is a syntactic sugar to easily write object-oriented code similarly to other OOP languages, but in the background, javascript still uses the prototype-based inheritance.

class Car {
  // Constructor
  constructor(name, year) {
    this.name = name; // this. auto creates a property
    this.year = year;
  }
  // Method
  age() {
    const date = new Date();
    return date.getFullYear() - this.year;
  }
}

Note that a class or its methods can be marked as static.

Inheritance

class Model extends Car {
  constructor(brand, mod) {
    super(brand); // super() lets you call parent class
    this.model = mod;
  }
  
  // Polymorphism is as simple as redefining parent method
  age() {
    return 1;
  }

  show() {
    return this.present() + ', it is a ' + this.model;
  }
}

Getters/Setter

Syntactically getters and setters are like special functions:

class Car {
  // Constructor
  constructor(name, year) {
    this.name = name; // this. auto creates a property
    this.year = year;
  }
  get carname() {
    return this.name;
  }
  set carname(x) {
    this.name = x;
  }
}

const myCar = new Car("BMW", 2022);
console.log(myCar.carname);

Visibility

Note that visibility attributes do not exist in javascript. There is no public, protected or private qualifiers here.