1559619257
In this article, we are going to deep dive into JavaScript prototype and understand how Object-Constructor relationship works
JavaScript is weird. If you are a seasoned JavaScript developer then you know that sometimes, it is completely different from other programming languages we are used to. For example, a function can be used as a mechanism to execute a piece of code in an isolated contextor a way to create objects. The weird thing is, in both the cases, function definition looks similar, it’s up to the compiler how it treats it.
In this article, we are going to focus exactly on creating objects by using functions. A function that is used, to create objects is called a constructor function. In JavaScript, almost everything is an object. Let’s understand it.
JavaScript has Primitive Data types and Reference Data types. number
, string
, boolean
, symbol
, null
, and undefined
are primitive data types. Primitive data type means when you create a variable, store a value of any given primitive data type in it, then declare another variable which is assigned (with the value) to the first variable, the second variable receives only a copy of the value from the first variable. Let’s see that in practice.
In the above example, we can see that variable name_max
was assigned with variable name_john
. Since the string
is a primitive data type, name_max
received only copy of the value from name_john
. Later, we assigned a new value to name_max
. This should change only the value stored in name_max
and should not affect name_john
in any way, which is proved here.
Reference data types work in different fashion. array
, object
and function
are reference data types. When you create a variable A
of reference data type (by assigning with a value of reference data type), the value is stored in the Heap and its memory reference is stored in the variable (this happens internally and _A_
is not a pointer). When you assign another variable B
with the variable A
such as B=A
, instead of copying the value of A
in the variable B
, the variable B
only gets the memory reference of the value A
points.
But unlike other programming languages, if you assign a new value to the variable B
, it won’t change the value of A
. JavaScript will instead assign a new memory in the Heap and store the value there. Here, A
and B
are now referencing different values in the memory.
But instead of assigning a new value to B
, if we are assigning a new value to the property of B
, JavaScript will use the referenced object and modify the property-value on it. Since A
is still pointing the same value in the memory, A
will get affected here. Let’s see that in action.
In the above example, we created variables morning
, mike
& odd
and then assigned a value of function
, object
and array
. Later we created variables evening
, john
& even
and assigned the given variables to them. Since, morning
, mike
& odd
points to the value of referenced data types, evening
, john
& even
will get only references to these values.
From the result, we can see that any changes made to the properties of the evening
, john
and even
modifies the value they point. Hence morning
, mike
& odd
are also modified. But in the case of kate
, since we are replacing the entire value, JavaScript allocates new memory for the value and mike
remains unaffected, as expected.
One weird thing you might have noticed in the above example is that we are adding a property info
on the morning
variable which is a function
. We know that we can add properties on an object, because traditionally an object is a map of keys and values like {x:y,}
. Then how this is possible?
In JavaScript, all referenced data types are objects, not in the traditional way though. Any variable which has **constructor**
property on it, is an object. I will explain constructor
in details later, but the important thing here to notice is that constructor
is like a function from which the object was created. If x.constructor
syntax returns a function, then x
is an object.
Not only that, all primitive data types except null
and undefined
are objects. A string is generated from String
constructor, a number is generated from Number
constructor, a boolean is generated from Boolean
constructor and symbol is generated from Symbol
constructor. Whenever we use literal syntax, JavaScript uses constructor functions behind the scene.
⚠️ As I said
null
is not an object but if you trytypeof null
, it returns"object"
which is not true. This is a noted JavaScript bug since the initial version of JavaScript.undefined
however is type ofundefined
.
Since we understood how almost everything in JavaScript is an object, it’s time to understand how to create an object from constructor function. Let’s first understand what a constructor function is.
A constructor function is like a normal function but it is invoked with **new**
keyword. We can pass arguments into it or use it as a first-class citizen. this
in a constructor function plays a vital role in object creation. this
inside a normal function call points to the execution context.
this
in a constructor function is the object it is going to create. Hence by modifying this
, we can add/remote properties on the object. Let’s see a simple demo in which we will create a very simple object.
In the above example, we created a function name Animal
. In JavaScript like other programming languages, we use constructor name with the first letter being uppercase, to look more like a class. Since we intend to use the Animal
function as a constructor function, this
inside the function will point to the object which will be created in the future. So, when the function execution starts, imagine this
is an empty object {}
.
Then we added a property name
to the object with the value received from the arguments. We also added a property getName
which is a function. This function returns a string and has access to the object in this
object. To understand this
in a normal function call,
After when we are done with our constructor function, we can speculate that what would be the object returned when it is invoked with new
keyword and proper arguments. As seen from the console output, we can see that object contains name
, getName
properties. name
the property has “Dog”
value and getName
is a function. When we call a.getName()
, this
inside getName
function points to a
and this.name
becomes a.name
.
In the above program, there is one more property constructor
on the object (this should be hidden but codesandbox shows it). Earlier, we discussed that any variable having this property (hidden or visible) is an object. Since, a
has it, it’s definitely an object. But what is it?
An object keeps the reference to the function constructor from which it was created inside constructor
property. In the previous program, we checked if the value of constrcutor
is equal to Animal
and it returned true
. Since, it is purely a reference, you should never override this property.
constructor property is not actually on the object a
but on its prototype. Let’s discuss prototype so that you will understand what it is and how it works.
A prototype is a kind of object which functions always have. This is saved inside the hidden prototype
property of a function. This isn’t much useful when we are using a function as a normal function to do or return something but it’s very useful when a function is used as a constructor.
In the previous example, let’s see what our Animal
prototype looks like.
As we can see, our Animal
prototype is empty.
Let’s take a look at Animal
constructor again. We have a property name
which can be different because we are receiving name
as an argument. Hence, every object created by Animal
constructor can have a different name and we understand that. But do we really need getName
function on every object? Can’t object reference a function with key getName
. This function might be stored somewhere in the memory and object just reference it. This way, we can save so much space and object doesn’t have to carry so many functions with it which increases its size.
This is where prototype comes into the picture. A prototype is an object associated with a constructor function. This object is like any other object containing keys and values. Here values can be a function or anything else you want. When we create an object using a constructor function, the object carries a reference to this prototype as it carries a reference to the constructor function as we saw earlier.
As I said, the object carries a reference to the prototype object of constructor function, it saves this reference in __proto__
property. When you access a property of an object, object first looks at its own and tries to search property there. If it finds the property, it returns that, end of discussion. But if it fails to find the property, it looks at the __proto__
object which points to the prototype
of the constructor function and tries to find property there.
Earlier I explained, if a variable has constructor
property, it is an object. This constructor property lives on prototype which proto points. Hence, we can access it from the object. Now we know that how we can move getName
function to the prototype.
From the above example, we moved getName
function to the Animal
prototype. We also added a static property (static because it never changes) generation
to the Animal
prototype. Then we created an object a
from Animal
constructor. By looking at Animal
constructor function, we can say that object should have only name
property and we can confirm that by looking at a
object in the console.
If we check Animal
prototype using Animal.prototype
, we can see getName
and generation
properties. Since object a
was constructed from Animal
, as per our discussion, it should have __proto__
property exactly like Animal.prototype
which we can verify visually. But how do we know a.__proto__
actually references Animal.prototype
. This can be validated by using strict equal comparison which returned true
.
⚠️ As I said
null
is not an object but if you trytypeof null
, it returns"object"
which is not true. This is a noted JavaScript bug since the initial version of JavaScript.undefined
however is type ofundefined
.
Since,getName
andgeneration
properties are on the prototype, we can safely access them on objecta
. When we doa.getName
ora.generation
, JavaScript first look for properties ona
, if not found then ona.__proto__
which is equal toAnimal.prototype
(tip: which is also equal to_a.constructor.prototype_
).
⚠️ As I saidnull
is not an object but if you trytypeof null
, it returns"object"
which is not true. This is a noted JavaScript bug since the initial version of JavaScript.undefined
however is type ofundefined
.### Prototype chain and Inheritance
As we know that every constructor function has a prototype object. Initially, it is empty but we can add more properties to it as we desire. And every object has access to it from __proto__
property.
If every object has __proto__
property, then since prototype is also an object then it must also have a constructor
and __proto__
property. Let’s see how it looks like on our Animal
constructor.
As we can see from the above result, constructor of a constructor function’s prototype is the constructor function itself. It also has __proto__
object which points to the prototype of Object
. Let’s see a magic trick.
In the above example, we added generation
property on the prototype and accessed it using a.generation
which works fine. But JavaScript also gives us a functional property hasOwnProperty
on the object a
which is used to check if the object a
has a property on it or its prototype. It returns true
if property passed to it is on the object a
else return false
if it is on its prototype or if it doesn’t exist at all. This is all fine but where the heck hasOwnProperty
property came from? We never defined it on a
or on Animal.prototype
.
As we discussed, when a property doesn’t exist on the object, JavaScript tries to find it on the __proto__
object which points to its prototype constructor function. But since prototype also has __proto__
object which points the prototype of its constructor function, it tries to find there. This cycle continues until there is no __proto__
property on the prototype object.
Let me again bring you the earlier test.
As you can see, Animal.prototype
was constructed from Object
constructor function, Anima.prototype
has __proto__
property which points to Object.prototype
. And Object.prototype
has hasOwnProperty
method. So a.hasOwnProperty()
call first tried to find hasOwnProperty
property on a
, then on Animal.prototype
(through _a.__proto___
), then on Object.prototype
(through _Animal.prototype.__proto___
). This is called as prototype chain. If you understood this, now you are close to understanding Inheritance in JavaScript based on prototype chain.
All objects in JavaScript travels back to Object’s prototype. Which means every object in JavaScript is created from Object constructor. Object constructor is generic and its prototype is not constructed from any constructor. Hence Object.prototype.__proto__
returns null
.
In simple language, inheritance means properties you got from your ancestors. Your parents borrowed some properties from their parents and you borrowed some properties from your parents.
Let’s understand a simple analogy. All animals can breathe and see. But only dogs can bark and cats can meow. Hence, dogs and cats inherit breathing property from animal kingdom but they have their own bark and meow property. This can be applied to Object Oriented programming.
Let’s talk about actual implementation now. Animal
constructor function can have breath
property. Dog
constructor function can have bark
property. And Cat
constructor function can have meow
property. Both Cat
and Dog
inherit properties from Animal
. This way, Dog
and Cat
constructor functions do not need to carry a huge burden of common properties and they can be shared through Animal
.
⚠️ As I said
null
is not an object but if you trytypeof null
, it returns"object"
which is not true. This is a noted JavaScript bug since the initial version of JavaScript.undefined
however is type ofundefined
.
Then how can we achieve this? One solution would be to saveAnimal.prototype
inDog.prototype
. This way can have all the methods defined inAnimal
prototype. But this is a wrong approach, let’s see.
In the above example, we created Animal
constructor function and Dog
constructor function. Then we added getClass
prototype function to Animal
. Then we assigned Dog.prototype
with Animal.prototype
hoping that all prototype properties of Animal
will be saved inside Dog.prototype
. Later, we changed Dog.prototype
by adding a new method getName
. By looking at the result, everything seems fine. But notice type of object d
, it is showing Animal
, this is weird because it should have been Dog
. Then what happened?
As we discussed before, the prototype is an object and when you assign one object with another object, only it’s reference is copied. Hence, Dog.prototype
is in reality is Animal.prototype
. Hence, if we add any property to Dog.prototype
, it will eventually end up on Animal
prototype.
Also, since Dog.prototype
is Animal.prototype
and it contains constructor
property which points to Animal
constructor function, JavaScript console shows that object d
is a type of Animal.
To avoid direct reference between these two prototypes, one might the copy (deep clone) Animal.prototype
object and assign it to Dog.prototype
. In that case, this won’t be an inheritance. We want Dog.prototype
not to carry methods of Animal.prototype
but only to reference them. This is where Object.create
function is useful. Read more about it on MDN.
Object.create(prototype, {property:propertyDescriptor, ...})
is a syntax for Object.create
function. This function returns an object, simple. This function accepts two arguments. The first prototype
argument is the prototype which will be given to the object in __proto__
property (we know that). The second argument is an object which contains property names and their descriptors. This second argument is used to add extra properties to the object. If nothing is passed in the second argument, the object will be empty.
Using this function, we are going to create an empty object with Animal
prototype and assign it to the Dog.prototype
. We will leave the second argument null because we don’t want to add any properties on Dog.prototype
yet. We will add them manually.
⚠️ As I said
null
is not an object but if you trytypeof null
, it returns"object"
which is not true. This is a noted JavaScript bug since the initial version of JavaScript.undefined
however is type ofundefined
.
Then we will add constructor property onDog.prototype
because it should be there for safety. Else, any object created fromDog.prototype
will still sayAnimal
because of prototype chain (you need to figure this one out, it’s simple).
From the above results, everything seems fine. Don’t hate me but this is still not inheritance. Since, Dog
only inherited prototype of Animal
, our object d
is missing class
property on it. Let’s expand the object d
and have a look.
The object d
is a type of Dog
and contains only property name
. Its prototype is a type of Animal
because it’s the prototype of Dog.prototype
. Dog.prototype
has getName
method and Animal.prototype
has getClass
method. We understood the prototype chain of d
, so far, so good.
But in the case of inheritance, your object inherits all the properties of a parent. In this case, we missed the property. Some people might argue that class
property should be on the prototype of Dog
but that’s wrong. A prototype should inherit the prototype of the parent and constructor function should inherit the implementation of parent’s constructor function.
So think about it, what we can do that imports the underlying implementation of Animal
constructor function inside Dog
constructor function. Well, the short answer is, you cant. But there is a way. What we want is to execute Animal
constructors code inside Dog
constructor so that d
get’s className
property. We also should be able to pass the argument className
.
If you have read my article on this
operator, then you know this
inside a function depends on the execution context. If you want to provide this
manually, you can use functionName.call or functionName.apply methods. So, what we want to do is execute Animal
function as a normal function from Dog
function context. In nutshell, it’s like executing Animal
constructor’s code inside Dog
constructor. We will use call
approach.
That’s it for the inheritance in JavaScript. I know this is a complicated subject but the way I explained, I hope it should have been relatively easy to understand. There is some extra information about the prototype.
Object.create
to link Animal.prototype
with Dog.prototype
but you can also use Object.setPrototypeOf function. This is used to set or override the prototype of an object. Implementation is here.☞ The Complete JavaScript Course 2019: Build Real Projects!
☞ JavaScript Bootcamp - Build Real World Applications
☞ JavaScript: Understanding the Weird Parts
#javascript #web-development
1622194980
It’s hard to skip prototypes (or the prototype chain or prototypal inheritance) if you want to dive deeper into JS development (Not only pure JS, but also Node.js, Frameworks like Vue.js, React.js, Angular,…).
If you are like me a few years ago and get some serious headache each time you have to deal with prototypes in JavaScript, this will probably be THE article you were looking for to get your head wrapped around the principle of prototypes in JS.
From the MDN documentation (don’t be scared, we’ll clarify everything below):
When it comes to inheritance, JavaScript only has one construct: objects. Each object has a private property (referred to as [[Prototype]]) which holds a link to another object called its prototype. That prototype object has a prototype of its own, and so on until an object is reached with null as its prototype. By definition, null has no prototype, and acts as the final link in this prototype chain.
Refer back to the below illustration whenever you feel the need, it might help you to wrap your head around this concept easier.
So let’s start from the base. Every object in JavaScript has a private [[Prototype]]
prototype, which holds a reference to another object (or null
). This means, that our new object will have access to methods and properties of that referenced object.
#javascript #prototypes #prototypal inheritance #prototype chain
1591242495
All you need to know about Prototypal Inheritance — The second pillar of Javascript
What we will learn here will help us understand Object-oriented programming(OOP).
#javascript #prototyping #prototype #prototype-chain #js
1595919780
You have probably heard of the terms prototypical inheritance and classical inheritance a lot. But what do they actually mean?
Before digging into these inheritance definitions, you need to understand what are prototypes and classes are in javascript.
A Prototype is an object that contains a list of methods and fields that are accessible by default.
Let’s take indexOf method from string for example. We never defined it but yet anytime we want to access this method from any string, we can do it.
#javascript #prototype #es5 #es6 #class
1595356020
In brushing up on my foundational JavaScript knowledge, I realized that I had never done a deep-dive on prototype. In the early days of my learning JavaScript, I had come across the __proto__
object property in the console. I clicked on it, saw a whole bunch of properties that I was not immediately concerned with, and made a mental note to someday investigate. Today is that day, and it turns out that I really should have investigated sooner as prototype is key to understanding how object properties are passed down to other instances of that object. Having learned JavaScript after becoming comfortable with the class-based nature of Ruby, an understanding of prototype would have cleared up some confusion around the differences between inheritance in the two languages.
While ES6 saw the introduction of the class
keyword in an attempt to make JavaScript appear more object-oriented, it is merely syntactic sugar. JavaScript at its heart is a prototype-based language. In my experience, I think this made it easy to take this syntactic sugar at face value, draw parallels to Ruby classes, and not delve deeper into the differences. And while this may make JavaScript more accessible to those familiar with class-based languages, it may mask the true nature of how inheritance in JavaScript occurs.
When we discuss inheritance in JavaScript we are talking about objects. Each object has a private property that connects it to its prototype (another object). Each prototype has its own prototype and the chain continues until we come to an object containing null
as its prototype. As null
represents nothing, it has no prototype and is the end of the prototype chain. All objects created in JavaScript are themselves instance of Object
and therefore have their own prototype chains descending from Object
.
JavaScript objects are dynamic and include a set of properties (termed own properties). They also are linked to a prototype object, which is linked to a prototype object and so on. When we attempt to access an object’s property, the property will be searched for on the object, then the prototype of the object and all the way along the prototype chain until the property is found or we reach null
on the chain. To illustrate:
let f = function() {
this.a = 1;
this.b = 2;
}
let o = new f();
f.prototype.b = 3;
f.prototype.c = 4;
console.log(o.a); // 1
console.log(o.b); // 2
console.log(o.c); // 4
console.log(o.d); // undefined
To begin, we create a function, f
, with properties of a=1
and b=2
. We then create an object, o
, from f
. Next, we add properties to the prototype of f
, creating a new property c=4
and updating b
to equal 3. When we log the properties of our object, o
, we are presented with the commented out results. The property of a
is 1, as expected. The property of b
is 2 because we look first on o
to see if there is a b
property. There is and its value is 2. We therefore never make it up the prototype chain to f
where the value of b
is 3. This is known as Property Shadowing. For the case of c
, we look to o
for a c
property and do not find one, leading us up to f
where the property of c
is found to equal 4. Finally, we are searching for the property of d
which is not a property of o
and neither is it a property of f
. We go all the way along the prototype chain to null
without finding d
and thus undefined
is the result.
#inheritance #web-development #prototype #javascript
1622207074
Who invented JavaScript, how it works, as we have given information about Programming language in our previous article ( What is PHP ), but today we will talk about what is JavaScript, why JavaScript is used The Answers to all such questions and much other information about JavaScript, you are going to get here today. Hope this information will work for you.
JavaScript language was invented by Brendan Eich in 1995. JavaScript is inspired by Java Programming Language. The first name of JavaScript was Mocha which was named by Marc Andreessen, Marc Andreessen is the founder of Netscape and in the same year Mocha was renamed LiveScript, and later in December 1995, it was renamed JavaScript which is still in trend.
JavaScript is a client-side scripting language used with HTML (Hypertext Markup Language). JavaScript is an Interpreted / Oriented language called JS in programming language JavaScript code can be run on any normal web browser. To run the code of JavaScript, we have to enable JavaScript of Web Browser. But some web browsers already have JavaScript enabled.
Today almost all websites are using it as web technology, mind is that there is maximum scope in JavaScript in the coming time, so if you want to become a programmer, then you can be very beneficial to learn JavaScript.
In JavaScript, ‘document.write‘ is used to represent a string on a browser.
<script type="text/javascript">
document.write("Hello World!");
</script>
<script type="text/javascript">
//single line comment
/* document.write("Hello"); */
</script>
#javascript #javascript code #javascript hello world #what is javascript #who invented javascript