Prototypes in Javascript in 5 minutes
JavaScript is an object-oriented language and according to Wilkipedia:
Object-oriented programming (OOP) is a programming paradigm based on the concept of "objects", which can contain data and code: data in the form of fields (often known as attributes or properties), and code, in the form of procedures (often known as methods).
So let’s dive into Javascript objects and their prototypes by building a simple object.
A method “message” was added with the anonymous function. “This” in the method is used to connect the variables inside of the method with the object.
const object = {
user: "guest",
where: "dev.to",
message: function () {
console.log(`${this.user}, welcome to ${this.where}`)
}
}
console.log(object) // result from the console
// {user: 'guest', where: 'dev.to', message: ƒ}
// message: ƒ ()
// user: "guest"
// where: "dev.to"
// [[Prototype]]: Object
console.log(object.message()) // guest, welcome to dev.to
console.log(object.__proto__)// result from the console
//{constructor: ƒ, __defineGetter__: ƒ, __defineSetter__: ƒ, //hasOwnProperty: ƒ, __lookupGetter__: ƒ, …}
//constructor: ƒ Object()
//hasOwnProperty: ƒ hasOwnProperty()
//isPrototypeOf: ƒ isPrototypeOf()
//propertyIsEnumerable: ƒ propertyIsEnumerable()
//toLocaleString: ƒ toLocaleString()
//toString: ƒ toString()
//valueOf: ƒ valueOf()
//__defineGetter__: ƒ __defineGetter__()
//__defineSetter__: ƒ __defineSetter__()
//__lookupGetter__: ƒ __lookupGetter__()
//__lookupSetter__: ƒ __lookupSetter__()
//__proto__: (...)
//get __proto__: ƒ __proto__()
//set __proto__: ƒ __proto__()
Pay attention that in the prototype of the object is a property of one more prototype and inside of this prototype can be one more prototype and so on.
Another way to get the prototype of the object is:
Object.getPrototypeOf(object)
Lets try to extract one of prototype’s method
console.log(object.hasOwnProperty()) // false
It works!
Let's add the same property to the object and console.log it:
const object = {
user: "guest",
where: "dev.to",
message: function () {
console.log(`${this.user}, welcome to ${this.where}`)
},
hasOwnProperty : function () {
console.log("the method was added to the object")
}
}
console.log(object.hasOwnProperty()) // the method was added to the object
So we can make an assumption about what the order of the search in the object is:
- First search in the object
- After in the prototype of the object
- After in the prototype of the prototype…
How to set prototype:
- With Object.create()
const objectWithProto = Object.create(object)
console.log(objectWithProto)// {} - empty object
console.log(objectWithProto.message()) // guest, welcome to dev.to - message method of prototype
console.log(objectWithProto.__proto__)// results from the console
//{user: 'guest', where: 'dev.to', message: ƒ}
//message: ƒ ()
//user: "guest"
//where: "dev.to"
//[[Prototype]]: Object
- With constructor
Creating constructor
function User (user, where) {
this.user = user;
this.where = where
}
Creating method for the prototype
const userPrototype = {
message () {
console.log(`${this.user}, welcome to ${this.where}`) }
}
Adding the method to the prototype of the object
User.prototype = userPrototype;
Adding User constructor to prototype (that takes parameters from the constructor and that can be passed to message method in the prototype)
User.prototype.constructor = User;
console.log(User) // ƒ User (user, where) {
this.user = user;
this.where = where
}
console.log(User.__proto__) // ƒ () { [native code] }
Let’s check what we’ve got:
const myUser = new User('Julie Cherner', ‘dev.to - author’);
myUser.message() // Julie Cherner, welcome to dev.to - author
console.log(myUser) // User {user: 'Julie Cherner', where: 'dev.to - author'}
console.log(myUser.__proto__) // results from console
//{message: ƒ, constructor: ƒ}
//constructor: ƒ User(user, where)
//message: ƒ message()
//[[Prototype]]: Object
So, prototypes provide great opportunities for the inheritance of properties for objects in Javascript.