Java Script Classes

Soner Mezgitci
5 min readApr 14, 2021

JavaScript has a special syntax for prototypical inheritance model is which called JavaScript classes. JavaScript classes is comparable inheritance in class-based object oriented languages.

JavaScript has a special syntax for prototypical inheritance model which is called JavaScript classes. JavaScript classes are comparable inheritance in class-based object oriented languages.

JavaScript classes are a special function. WhenThe ECMAScript 2015 specification brought a lot of improvements, the largest set of changes the language has seen to-date. Classes are added to ES6. They behave like the class keyword from these other languages. We can make class declarations and class expressions because they are just functions. Since they are functions there is nothing stopping us from making declarations and function expressions when we are implementing our classes. Classes provide templates to create new objects easier. Classes are just regular functions and they can replicate without using class syntax. It is special syntactic sugar added in ES6 to make it easier to declare and inherit complex objects.

Creating JavaScript Class

JavaScript class is similar to the JavaScript constructor function, and it is just a syntactic sugar.

The constructor function is defined as:

// constructor function
function Person () {
this.name = 'Soner',
this.age = 40
}
// create an object
const person1 = new Person();

Instead of using the function keyword, you use the class keyword for creating JS classes. For example,

// creating a class
class Person {
constructor(name) {
this.name = name;
}
}

The class keyword is used to create a class. The properties are assigned in a constructor function.

Now you can create an object. For example,

// creating a class
class Person {
constructor(name) {
this.name = name;
}
}
// creating an object
const person1 = new Person('John');
const person2 = new Person('Jack');
console.log(person1.name); // John
console.log(person2.name); // Jack

Here, person1 and person2 are objects of Person class.

Note: The constructor() method inside a class gets called automatically each time an object is created.

Prototypes:

When we make class maps to JavaScript’s underlying prototype. We can see like this;

  • When we call a constructor object will be created.
  • Prototype connections;
  • Property & method delegation;
  • Emulating classes with prototypes.

Creating Objects with Constructor Calls

As we all know about how constructors work. Calling a function with a new keyword will return an object. This makes a constructor call and functions also called in the constructor. I will try to show it in the example below.

"use strict";

function Food (name, protein, carbs, fat) {
this.name = name;
this.protein = protein;
this.carbs = carbs;
this.fat = fat;
}

// Calling Food with 'new' is a "constructor call", and results in its returning an object
const chicken_breast = new Food('Chicken Breast', 26, 0, 3.5);
console.log(chicken_breast.protein) // 26

// Failing to call Food with 'new' results in its returning 'undefined'
const fish = Food('Halibut', 26, 0, 2);
console.log(fish); // 'undefined'

When you call a function with new, four things happen under the hood:

Calling a function with new, There is a couple operations works behind the scene

  1. New object created. (0)
  2. O connected to another object which is called prototype;
  3. The function’s this set the value to O
  4. Functions return O

The engine executes to functions with this logic

We can rewrite our Food function to work without the new keyword:

"use strict";

// Eliminating the need for 'new' -- just for demonstration
function Food (name, protein, carbs, fat) {
// Step One: Create a new Object
const obj = { };

// Step Two: Link prototypes -- we'll cover this in greater detail shortly
Object.setPrototypeOf(obj, Food.prototype);

// Step Three: Set 'this' to point to our new Object
// Since we can't reset `this` inside of a running execution context,
// we simulate Step Three by using 'obj' instead of 'this'
obj.name = name;
obj.protein = protein;
obj.carbs = carbs;
obj.fat = fat;

// Step Four: Return the newly created object
return obj;
}

const fish = Food('Halibut', 26, 0, 2);
console.log(fish.protein); // 26

Those steps are very common steps in classes. We can create an object and assign properties and returning a new object with a return statement gives headache to most developers. This is the worst part of prototype.

Prototype Chain

Normally all objects in JavaScript functions connect to another object. We call this operation prototype. If we try to create an object with regular function it will copy and hold too many spaces in the memory. Let’s say we want to create 100 students each time we create a new student it will copy the function and create new students each time when the function executes. But if we use a prototype no matter how many objects you are created functions just executes ones in the memory and allows you to overwrite functions if it’s needed.

"use strict";

// joe has no toString property . . .
const joe = { name : 'Joe' },
sara = { name : 'Sara' };

Object.hasOwnProperty(joe, toString); // false
Object.hasOwnProperty(sara, toString); // false

// . . . But we can call it anyway!
joe.toString(); // '[object Object]', instead of ReferenceError!
sara.toString(); // '[object Object]', instead of ReferenceError!

The output from our toString calls is utterly useless, but note that this snippet doesn't raise a single ReferenceError! That's because, while neither joe or sara has a toString property, their prototype does.

When we look for sara.toString(), sara says, "I don't have a toString property. Ask my prototype." JavaScript, obligingly, does as told, and asks Object.prototype if it has a toString property. Since it does, it hands Object.prototype's toString back to our program, which executes it.

It doesn’t matter that sara didn't have the property herself -- we just delegated the lookup to the prototype.

In other words, we can access non-existent properties on an object as long as that object’s prototype does have those properties. We can take advantage of this by assigning properties and methods to an object’s prototype, so that we can use them as if they existed on the object itself.

Even better, if several objects share the same prototype — as is the case with joe and sara above -- they can all access that prototype's properties, immediately after we assign them, without our having to copy those properties or methods to each individual object.

This is what people generally refer to as prototypical/prototypal inheritance — if my object doesn’t have it, but my object’s prototype does, my object inherits the property.

In reality, there’s no “inheritance” going on, here. In class-oriented languages, inheritance implies behavior is copied from a parent to a child. In JavaScript, no such copying takes place — which is, in fact, one of the major benefits of prototypes over classes.

Here’s a quick recap before we see precisely where these prototypes come from:

  • joe and sara do not "inherit" a toString property;
  • joe and sara, as a matter of fact, do not "inherit" from Object.prototype at all;
  • joe and sara are linked to Object.prototype;
  • Both joe and sara are linked to the same Object.prototype.
  • To find the prototype of an object — let’s call it O — you use: Object.getPrototypeOf(O).

And, just to hammer it home: Objects do not “inherit from” their prototypes. They delegate to them.

--

--

Soner Mezgitci

Software Engineer | Ruby on Rails | JavaScript | HTML5 | CSS | PostgreSQL | React | Redux