Skip to content

JavaScript Tutorial Prototypes

Constructor Functions and the prototype Property

Lesson 199 of 258 2 min read By Deepak Paswan Updated Oct 4, 2026

Before the class keyword (ES2015), JavaScript used constructor functions to create many similar objects. You will still see them in older code, and they show how classes work underneath.

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

Person.prototype.greet = function () {
  return `Hi, I am ${this.name}`;
};

const maya = new Person("Maya", 28);
const arjun = new Person("Arjun", 31);

console.log(maya.greet());          // → Hi, I am Maya
console.log(maya.greet === arjun.greet); // → true   (one shared function)
console.log(maya instanceof Person);     // → true

By convention, constructor names start with a capital letter, and you call them with new.

What new does

new Person("Maya", 28) does four steps:

  1. Creates a new empty object.
  2. Sets that object’s prototype to Person.prototype.
  3. Runs the function with this pointing at the new object.
  4. Returns the object (unless the function returns a different object).
script.js
JS
function Person(name) { this.name = name; }

const p = new Person("Maya");
console.log(Object.getPrototypeOf(p) === Person.prototype); // → true
console.log(p.constructor === Person);                      // → true

Why methods go on the prototype

If you write this.greet = function () {...} inside the constructor, every instance gets its own copy of the function, which wastes memory. Putting it on Person.prototype shares one copy.

script.js
JS
function A() { this.hello = function () {}; }
function B() {}
B.prototype.hello = function () {};

console.log(new A().hello === new A().hello); // → false  (two functions)
console.log(new B().hello === new B().hello); // → true   (shared)

Forgetting new

script.js
JS
function Person(name) { this.name = name; }

try {
  const p = Person("Maya");        // forgot new: `this` is not a new object
  console.log(p);                  // → undefined
} catch (error) {
  console.log(error.name);
}

Without new, in sloppy mode this becomes the global object, and you accidentally set window.name. In strict mode it throws. Classes prevent this: calling a class without new is always an error.

Inheritance the old way

script.js
JS
function Animal(name) { this.name = name; }
Animal.prototype.speak = function () { return this.name + " makes a sound"; };

function Dog(name) { Animal.call(this, name); }          // run the parent constructor
Dog.prototype = Object.create(Animal.prototype);         // link the prototypes
Dog.prototype.constructor = Dog;
Dog.prototype.speak = function () { return this.name + " barks"; };

console.log(new Dog("Rex").speak());          // → Rex barks
console.log(new Dog("Rex") instanceof Animal); // → true

That is several lines of fiddly set-up, and it is easy to get wrong. This is the main reason class ... extends was added.

Same thing as a class

script.js
JS
class Person {
  constructor(name) { this.name = name; }
  greet() { return `Hi, I am ${this.name}`; }
}

console.log(typeof Person);                                // → function
console.log(typeof Person.prototype.greet);                // → function

The next lesson compares the two: Classes and Prototypes.