Everything is inherited from the Object Prototype in Javascript.

Rehmat Sayany
5 min readApr 1, 2024
typeof class and function

In this blog, you ll learn

  1. Why typeof class is `function`
  2. Why can we use methods of objects in array, string, and function?
  3. Unraveling Prototypal Inheritance:
  4. Embracing the Object Hierarchy:

Introduction:

As a language, JavaScript often presents developers with intriguing quirks and behaviors. One such phenomenon is the result of using the typeof operator on both class and function declarations, which returns 'function'. This blog will explore the reasons behind this seemingly counterintuitive behavior, shedding light on JavaScript's inner workings of a prototype-based inheritance system.

The Advent of Classes in JavaScript

With the advent of ECMAScript 6 (ES6), JavaScript introduced classes, providing developers with a more structured and familiar syntax for object-oriented programming. Despite their syntax resembling classical inheritance, classes in JavaScript are primarily syntactic sugar over the prototype-based system that JavaScript has always had.

Have you ever wondered how a constructor is called automatically when we create an object of class? Don't worry you will get your answer at the end of this blog.

Under the hood, the class keyword in JavaScript works by leveraging JavaScript's existing prototype-based inheritance system while providing a more familiar and convenient syntax for defining object-oriented structures. When you define a class using the class keyword, JavaScript essentially performs several steps behind the scenes to create a constructor function and set up the prototype chain. Here's a simplified overview of how it works:

Class Declaration: When you declare a class using the class keyword, JavaScript creates a new object that acts as a blueprint for instances of that class. This object contains methods and properties defined within the class definition.

class Student { 
constructor(name, age) {
this.name = name;
this.age = age;

}
getAge() {
return this.age;
}
}

How does it look under the hood?



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

Student.prototype.getAge = function() {
return this.age;
};


const rehmat = new Student('Rehmat', 20);

console.log(rehmat.getAge()); // 20

So now you got my point? there are no real classes in JavaScript. Everything is a function, which is why when you use typeof with class, the return type is function.

Now let's move one step forward and see why we can use methods of objects in array, string, and also in function.

JavaScript, with its versatility and dynamic nature, often leads to intriguing discoveries. One such concept is the idea that everything in JavaScript is an object, whether it’s a primitive value like a string or a complex structure like a function or an array. Lets take an example.

Here you can see a function named Student.

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

console.log(typeof Student); // Output: 'function'
console.log(Student.length); // Output: 2(number of parameters)
console.log(Student.name); // Output: 'Student'

Despite being declared as a function, Student exhibits object-like properties. The typeof operator returns 'function', but you can also access properties like length and name. This behavior is not unique to Student—all functions in JavaScript possess these properties, thanks to JavaScript's flexible and dynamic nature.

Extending Functions with Properties

The magic doesn’t stop there. You can dynamically add properties and methods to functions, further blurring the distinction between functions and traditional objects:



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

Student.rehmat = function() {
return 'Rehmat';
};

console.log(Student.rehmat()); // Rehmat

Here, we’ve added a property rehmat to the Student function. Despite being declared as a function, Student now behaves like an object with an additional property. This showcases the dynamic nature of JavaScript functions and their ability to evolve beyond their initial definition.

At the heart of JavaScript lies the Object prototype, from which all other objects inherit. Whether it's functions, arrays, strings, or custom objects, everything in JavaScript ultimately traces its lineage back to Object. This unifying principle underscores JavaScript's simplicity and elegance, empowering developers to work with a consistent set of principles and patterns.

Heart of javascript Object prototype

This is due to JavaScript's prototype-based inheritance model, which forms the foundation of its object-oriented programming paradigm.

Strings as Objects:

Although str appears to be a simple string, it possesses object-like properties and behaviors. Let's delve deeper into its object-like characteristics:

const str = 'rehmat';

Prototype Inheritance:

console.log(str.__proto__ === String.prototype); // true
console.log(str.__proto__.__proto__ === Object.prototype); // true

The __proto__ property of str points to the String prototype, which, in turn, inherits from the Object prototype. This establishes a prototypal chain that links the string str to the Object prototype, imbuing it with object-like features.

Object Methods on Strings:

console.log(str.hasOwnProperty('length')); // true
console.log(str.hasOwnProperty('rehmat')); // false

Despite being a string, str can utilize object methods like hasOwnProperty. This behavior is a result of JavaScript's prototypal inheritance model, which allows objects—including strings—to inherit properties and methods from their prototype chain.

Prototype object.

Indeed, the length property, present in various data types such as functions, strings, arrays, and even objects, stems from JavaScript's prototypal inheritance model. As you correctly pointed out, these data types inherit this property from the Object prototype, which serves as the foundation of their inheritance chain.

Inheritance of Length Property:

Let’s examine how the length property is inherited across different data types:

  1. Functions
  2. Array
  3. Objets
  4. String
function myFunction(a, b) {}
console.log(myFunction.length); // Output: 2

// array
const myArray = [1, 2, 3];
console.log(myArray.length); // Output: 3

// objects
const myObject = { a: 1, b: 2, c: 3 };
console.log(Object.keys(myObject).length); // Output: 3

//string
const myString = 'Hello';
console.log(myString.length); // Output: 5

Understanding this inheritance mechanism underscores the elegance and simplicity of JavaScript’s object-oriented model, empowering developers to write expressive and concise code while leveraging the language’s versatile features.

--

--

Rehmat Sayany

Full Stack developer @westwing passionate about NodeJS, TypeScript, React JS and AWS.