We han inherit by Object.create(<baseobject>).

Constructor functions

new keyword automatically return the object. new changes this to the object which we would like to create. Example:

function Elf(name, weapon) {
  this.name = name;
  this.weapon = weapon;
}

Elf.prototype.attack = function () {
  console.log(`${this.name} attacks with ${this.weapon}`);
};

const elf1 = new Elf('Peter', 'stones');
const elf2 = new Elf('Vasya', 'fire');
elf1.attack();
elf2.attack();

We can’t use arrow function to create an attach function, because arrow functions are lexically scouped and this will be equal to the global object:

// wrong way:
Elf.prototype.attack = () => {
  console.log(`${this.name} attacks with ${this.weapon}`);
};

But regular functions are dynamically scoped

Using functions inside of methods.

In case we using functions inside of methods, this will be working a bit diffrent way. There are the following ways how to fix this:

Elf.prototype.build = function () {
  function building() {
    return `${this.name} build a house`;
  }
  building.call(this);
};

or

Elf.prototype.build = function () {
  let self = this;
  function building() {
    return `${self.name} build a house`;
  }
  building();
};

ES6 Classes

The same with classes:

class Elf {
  constructor(name, weapon) {
    this.name = name;
    this.weapon = weapon;
  }

  attack() {
    console.log(`${this.name} attacks with ${this.weapon}`);
  }
}

const elf1 = new Elf('Peter', 'stones');
elf1.attack();

This is actually a syntax sugar.

Summarise of this

There are 4 ways:

new binding this

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

implicit binding

const person = {
  name: 'Vasya',
  age: 44,
  hi() {
    console.log(`Hi ${this.name}`);
  }
}

explicit binding

const person = {
  name: 'Vasya',
  age: 44,
  hi: function () {
    console.log(`Hi ${this.name}` + this.setTimeout);
  }.bind(window),
};

arrow functions

const person = {
  name: 'Vasya',
  age: 44,
  hi: function () {
    const inner = () => this.setTimeout
    console.log(`Hi ${this.name}` + inner());
  }.bind(window),
};

Inheritance

Example:

class Charackter {
  constructor(name, weapon) {
    this.name = name;
    this.weapon = weapon;
  }

  attack() {
    console.log(`${this.name} attacks with ${this.weapon}`);
  }
}

class Elf extends Charackter {
  constructor(name, weapon, type) {
    super(name, weapon);
    this.type = type;
  }
}

class Ogre extends Charackter {
  constructor(name, weapon, color) {
    super(name, weapon);
    this.color = color;
  }

  makeFort() {
    console.log(`${this.name} colored with ${this.color} has created a fort`);
  }
}

Private or Public

It works only for ES2020

class Ogre extends Charackter {
  age = 56;
  constructor(name, weapon, color) {
    super(name, weapon);
    this.color = color;
  }

  private makeFort() {
    console.log(`${this.name} colored with ${this.color} has created a fort`);
  }
}