Trying to understand the difference between prototype and constructor in JavaScript

JavascriptPrototype

Javascript Problem Overview


I'm new to JavaScript ,to understand this concept i have read many articles regarding prototype and constructors but where ever i go i'm left with confusion.

The confusion arises when people talk about constructor and prototype simultaneously.

In the following example

var employee = function Emp(name) {
    this.name = name;
}
var jack = new employee("Jack Dwain");

employee.constructor //gives Function()

employee.prototype // gives  Emp {}

employee.prototype.constructor //gives Emp(name)

jack.constructor //gives Emp(name)

jack.prototype //gives undefined
  1. prototype is a way JS achieves inheritance,since Emp(name) is the base function prototype is referenced to the same function itself. Is that what happened?

  2. In what way employee.constructor and employee.prototype.constructor differ?

  3. Why was jack.prototype is undefined i.e If it is inheriting from the function Emp(name) why it didn't reference that function?

  4. How can I clearly predict myself without typing in the console what the prototype or the constructor or the prototype.constructor ......yields

Javascript Solutions


Solution 1 - Javascript

Its a pretty hard thing to wrap your mind around if you are used to the ease of extending objects in other OOP languages, but I'll do my best to explain the uses of those and what is what. I am going to assume you are familiar with other OOP languages. Correct me if I'm wrong.

All functions have the prototype Function(). They are inheriting all base functionality from Function like toString() and valueOf().

Then there is a constructor. That is what you use to initialize an object with.

p = new Foo();

So in this case we have two things.

  • A function Foo with Function as prototype(Foo)
  • A Function object with Foo() as constructor(p)

(following me yet?)

The Foo() constructor can override some base functionality of the Function constructor, but also leave it as it is and make good use of it.

If you are familiar with OOP principles, The prototype is the base class, the constructor your current class. in OOP the above would be class Foo extends Function

You can also start inheritance with this entire setup of prototype and constructor making more complex objects as you go whilst sharing functionality.

For example this:

// make a object initialiser extending Function. in oop `class Foo extends Function`

function Foo(bar) {
    this.baz = bar;
}
Foo.prototype.append = function(what) {
    this.baz += " " + what;
};
Foo.prototype.get() {
    return this.baz
}

Now lets say we want different ways to get baz out of there. one for console logging and one for putting it on the title bar. We could make a big thing about our class Foo, but we dont do that, because we need to do wholly different things with the new classes but are made for different implementations. The only thing they need to share are the baz item and the setters and getters.

So we need to extend it to use an OOP term. in OOp this would be the desired end result class Title extends Foo(){}. So lets take a look how to get there.

function Title(what) {
    this.message = what;
}

At this point the Title function looks like this:

  • prototype Function
  • constructor Title

So, to make it extends Foo we need to change the prototype.

Title.prototype = new Foo();
  • prototype Foo
  • constructor Foo

This is done by initializing a new Foo() object against the prototype. Now its basically a Foo object called Title. That is not what we want because now we cant access the message part in Title. We can make it properly extend Foo() by resetting the constructor to Title

Title.prototype.constructor = Title;
  • prototype Foo
  • Constructor Title

Now we are faced with one more problem. The constructor of Foo doesn't get initialized so we end up with an undefined this.baz

To resolve that we need to call the parent. In java you would do that with super(vars), in php $parent->__construct($vars).

In javascript we have to modify the Title class constructor to call the constructor of the parent object.

So the Title class constructor would become

function Title(what) {
    Foo.call(this,what);
    this.message = what;
}

By using the Function object property Foo inherited we can initialism the Foo object in the Title object.

And now you have a properly inherited object.

So instead of using a keyword like extend like other OOP languages it uses prototype and constructor.

Solution 2 - Javascript

If you want to create a javascript object you can simply declare a new object and give it properties (I've chosen to objectify myself):

var myself= {
    name:"Niddro",
    age:32
};

This method allows you to make one object. If what you want to have is a prototype describing a person in general, where you can declare several people with the same setup. To create a prototype, you can use a constructor, as seen below:

//Constructor
function generalNameForObject(param1, param2,...) {
    //Give the object some properties...
}

I have a prototype (a recipe) in mind that I want to call person and it should contain the properties name and age and I'll use a constructor to make it:

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

The above construct function describes the prototype for my person objects.

Create a new person by calling the construct function:

var myself = new person("Niddro",31);
var OP = new person("rajashekar thirumala",23);

Some time passes and I realise that I've had a birthday so I need to change the property of the prototype:

myself.age=32;

If you want to add properties to the construct, you need to manually add it into the construct function:

function person(name,age,rep) {
    this.name=name;
    this.age=age;
    this.reputation=rep;
}

Instead, you can add properties to the prototype by doing the following (here "prototype" is an actual command and not just a name):

function person(name,age,rep) {
    this.name=name;
    this.age=age;
}
person.prototype.reputation=105;

note that this will add a reputation of 105 for all objects created.

I hope this has given you some more insight on the relationship between the constructor and prototype.

Solution 3 - Javascript

> employee.constructor //gives Function()

In JavaScript functions are also objects, which can be constructed using its own constructor which is Function . So you can write following code to get a instance of Function.

var employee2 = new Function('a', 'b', 'return a+b');

Same happens when you create function using function literal like in your case. And the constructor property of this object also refers to the same native Function object/class.

> employee.prototype // gives Emp {}

Each object in JavaScript has a prototype associated with it. Though only function objects prototype is directly accessible with the .prototype. This same prototype is copied on its objects prototype when you create objects with new keyword. Primarily this copying is responsible for the inheritance/extension. Although the prototype is copied, it is not directly asseccible like in case of Function objects. It's available in non standard way with .__proto__ . Following code will return true.

jack.__proto__==employee.prototype

> employee.prototype.constructor //gives Emp(name)

As said in the documentation of Object.prototype.constructor . This returns a reference to the Object function that created the instance's prototype. Here the object being refered is employee.prototype and not employee. This is bit complex but prototype of object employee.prototype was created by the function Emp(name)

> jack.constructor //gives Emp(name)

As said in the previous point, this objects prototype was created by function Emp(name) when you created the object using new Emp(),

> jack.prototype //gives undefined

jack is not a function object, so you cant access its prototype like that. You can access(not a standard way) the prototype of jack like following.

jack.__proto__

Solution 4 - Javascript

Constructor:

function Foo(x) {
	this.x =x;
}

Foo is the constructor. A constructor is a function.

There are two ways to use this constructor Foo.

> "Objects are created by using constructors in new expressions; for > example, new Date(2009,11) creates a new Date object. Invoking a > constructor without using new has consequences that depend on the > constructor. For example, Date() produces a string representation of > the current date and time rather than an object."

Source ECMA-262

That means if Foo returns something (via return "somevalue";) then typeof Foo() is the type of the return value.

On the other hand, when you call

var o = new Foo();

JavaScript actually just does

var o = new Object();
o.[[Prototype]] = Foo.prototype;
Foo.call(o);

Prototype:

When you call o.a, then javascript first checks if a is a own property of the object o. If not javascript will look up the property chain to find a.

For more information about property-chain have a look at mdn.

The prototype porperty of the constructor has a really powerful feature, that is not available in classes. If it's useful is another debate. The prototype porperty of the constructor can alter properties of each instance that does link to that prototype in their prototype-chain.

TL,DR:

Note: This is not an exact definition, the purpose of the summary is just to give you a feeling about constructors and prototypes.

If you use a constructor with the new keyword, then constructors and prototypes have kind of similar purpose even though they are completely different. A constructor initializes properties of the object, so it provides properties. A prototype also provides properties via the property-chain (prototype-based inheritance).

Solution 5 - Javascript

A prototype is just an object, while a constructor is a pointer to the function that created the object.

A constructor is a pointer. It points to the Function() that created the point from which you are retrieving the constructor from. (i.e a constructor is just a reference to a Function() and we can call it as many times as we want.)

One of the uses of the constructor is to help you create replicate copies of an object. Since the constructor property is a reference to the function that created the object, as long as you have a copy of the object, it will always point to the original constructor.https://coderwall.com/p/qjzbig/understanding-constructor-and-prototype

Using an Object Constructor: Usually, an object created alone is limited in many situations. It only creates a single object.

Sometimes we like to have an "object type" that can be used to create many objects of one type.

The standard way to create an "object type" is to use an object constructor function:

function person(first, last, email ) {
  this.first_name = first;
  this.last_name = last;
  this.e_mail = email;
}
var myFather = new person("Ibm", "Muh", "[email protected]");

The above function (person) is an object constructor. Once you have an object constructor, you can create new objects of the same type:

var myFather = new person("Sul", "Ahm", "[email protected]");

Every JavaScript object has a prototype. A prototype is also an object.

All JavaScript objects inherit their properties and methods from their prototype.

Objects are created using 2 methods of creating an object i.e (1) object literal, or (2) with new Object(), inherit from a prototype called Object.prototype. Objects created with new Date() inherit the Date.prototype.

The Object.prototype is on the top of the prototype chain.

All JavaScript objects (Date, Array, RegExp, Function, ....) inherit from the Object.prototype.https://www.w3schools.com/js/js_object_prototypes.asp

The keyword prototype is a property of Function() objects.

Value of a prototype is the object constructor that created that specific object. Let's see a couple of prototypes:

Boolean.prototype // returns Object Boolean
String.prototype // returns Object String with methods such as "toUpperCase"
Function.prototype // returns function() {} or function Empty() {}

Creating a Prototype:

The standard way to create an object prototype is to use an object constructor function:

function Person(first, last, age, eyecolor) {
  this.firstName = first;
  this.lastName = last;
  this.age = age;
}
var myFather = new Person("John", "Doe", 50);

With a constructor function, you can use the new keyword to create new objects from the same prototype as shown above:

The constructor function is the prototype for Person objects. It is considered good practice to name constructor function with an upper-case first letter.

Adding Properties to a Prototype

You cannot add a new property to a prototype the same way as you add a new property to an existing object, because the prototype is not an existing object.

Example: Person.nationality = "English";

To add a new property to a prototype, you must add it to the constructor function:

function Person(first, last, age, eyecolor) {
  this.firstName = first;
  this.lastName = last;
  this.age = age;
  this.eyeColor = eyecolor;
  this.nationality = "English";
}

All native and complex objects retrieve to their original constructors, which in this case are themselves. The only exception is the Function prototype, which returns the Function() function that created it. Don't confuse it with the constructor, as it's not the same.

Function.prototype === Function.constructor // returns false, Function.constructor is function Function(){}

There's an extra property, __proto__, which refers to the internal [[proto]] property of instance objects. Unlike Function() objects, every Object has a __proto__. It's not recommended to update the prototype of an instance object, as prototypes are not meant to be changed on runtime (you should be able to see who's the proto of who, otherwise you need to spent extra computation in ensuring no cyclic references).

Solution 6 - Javascript

Yet the truth is, this approach might be wrong for many situations. In Javascript when you bind a method to the this keyword, you are providing that method to only that particular instance and it does not really have any relationship with an object instance of that constructor, pretty much like a static method. Keeping in mind that functions are first-class citizens in Javascript, we can deal with them just like objects, in this case we're only adding a property to an instance of a function object. Thats only part of the story, you must also know that any method attached via this will get re-declared for every new instance we create, which could affect the memory usage of the application negatively if we wish to create so many instances.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionEin2012View Question on Stackoverflow
Solution 1 - JavascriptTschallackaView Answer on Stackoverflow
Solution 2 - JavascriptNiddroView Answer on Stackoverflow
Solution 3 - JavascriptVishwanathView Answer on Stackoverflow
Solution 4 - Javascriptuser8175891View Answer on Stackoverflow
Solution 5 - JavascriptUstasView Answer on Stackoverflow
Solution 6 - JavascriptabdulwahhabView Answer on Stackoverflow