Object oriented programming in JavaScript

there are several layers to object-oriented programming in
JavaScript

OOP with single objects
Prototype chains
Constructors & Classes

Inheritance

SINGLE OBJECTS

objects are building blocks of JavaScript OOP and they are simple
maps from strings to values

 

properties
entries in the map


methods
properties whose values are functions
in which the this keyword refers to the receiver of the method call 

object literal 

var foobar = {
  name: 'Foo',
  surname: 'Bar',

  getInfo: function () {
    return this.name + ' ' + this.surname;
  }
};

foobar.name //=> "Foo"
foobar.surename //=> "Bar"

foobar.getInfo(); //=> "Foo Bar"

foobar.name = 'Bar';
foobar.surname = 'Foo';
foobar.getInfo(); //=> "Bar Foo"

a few common patterns

  • refactoring a switch/case statement
  • holding constant strings
  • etc.

sharing properties

it is easy to declare an object for a single person
but it becomes problematic when we have to add more persons

var fizzbuzz = {
  name: 'Fizz',
  surname: 'Buzz',

  getInfo: function () {
    return this.name + ' ' + this.surname;
  }
};

problems with this approach

PROTOTYPE CHAINS

(delegation)

both objects share the same prototype object
both prototype chaning work like single objects 

var Person = {
  getInfo: function () {
    return this.name + ' ' + this.surname;
  }
};

var foobar = Object.create(Person);

foobar.name = 'Foo';
foobar.surname = 'Bar';

var fizzbuzz = Object.create(Person);

fizzbuzz.name = 'Fizz';
fizzbuzz.surname = 'Buzz';


foobar.getInfo(); //=> "Foo Bar"
fizzbuzz.getInfo(); //=> "Fizz Buzz"

ECMAScript 5 solution

var Person = {
  getInfo: function () {
    return this.name + ' ' + this.surname;
  }
};

var foobar = {
  __proto__: Person,
  name: 'Far',
  surname: 'Bar'
};

var fizzbuzz = {
  __proto__: Person,
  name: 'Fizz',
  surname: 'Buzz'
};


foobar.getInfo(); //=> "Foo Bar"
fizzbuzz.getInfo(); //=> "Fizz Buzz"

ECMAScript 2015 solution

CONSTRUCTORS

function Person(name, surname) {
  this.name = name;
  this.surname = surname;

  this.getInfo = function () {
    return this.name + ' ' + this.surname;
  };
};

var foobar = new Person('Foo', 'Bar');
var fizzbuzz = new Person('Fizz', 'Buzz');

foobar.getInfo(); //=> "Foo Bar"
fizzbuzz.getInfo(); //=> "Fizz Buzz"

a constructor function for Person

both instances have the getInfo() method
how do we remove this redundancy?

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

Person.prototype.getInfo = function () {
  return this.name + ' ' + this.surname;
};


var foobar = new Person('Foo', 'Bar');
var fizzbuzz = new Person('Fizz', 'Buzz');

foobar.getInfo(); //=> "Foo Bar"
fizzbuzz.getInfo(); //=> "Fizz Buzz"

sharing methods (delegation)

CLASSES (ES2015)

class Person {
  constructor(name, surname) {
    this.name = name;
    this.surname = surname;
  }

  getInfo() {
    return this.name + ' ' + this.surname;
  }
}

var foobar = new Person('Foo', 'Bar');
var fizzbuzz = new Person('Fizz', 'Buzz');

foobar.getInfo(); //=> "Foo Bar"
fizzbuzz.getInfo(); //=> "Fizz Buzz"

a Person class

INHERITANCE

having in mind the Person constructor

our goal is to derive Employee from it

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

Person.prototype.getInfo = function () {
  return this.name + ' ' + this.surname;
};

function Employee(name, surname, department) {
  Person.call(this, name, surname); // inherit instance properties
  this.department = department;      // create sub class specific properties
}

// Inherit Person.prototype properties
Employee.prototype = Object.create(Person.prototype);

// Override Person.prototype.getInfo method
Employee.prototype.getInfo = function () {
  return Person.prototype.getInfo.call(this) + ' (' + this.department + ')';
};

var johnsmith = new Employee('John', 'Smith', 'IT Department');

johnsmith.getInfo(); //=> "John Smith (IT Department)"

using ECMAScript 2015 classes

class Person {
  constructor(name, surname) {
    this.name = name;
    this.surname = surname;
  }

  getInfo() {
    return this.name + ' ' + this.surname;
  }
}

class Employee extends Person {
  constructor(name, surname, department) {
    super(name, surname);          // inherit instance properties
    this.department = department;  // create sub class specific properties
  }

  getInfo() {
    return super.getInfo() + ' (' + this.department + ')';
  }
}

var johnsmith = new Employee('John', 'Smith', 'IT Department');

johnsmith.getInfo(); //=> "John Smith (IT Department)"
Made with Slides.com