Cookie Consent by Free Privacy Policy Generator ๐Ÿ“Œ Why JavaScript is a Prototype-based OOP

๐Ÿ  Team IT Security News

TSecurity.de ist eine Online-Plattform, die sich auf die Bereitstellung von Informationen,alle 15 Minuten neuste Nachrichten, Bildungsressourcen und Dienstleistungen rund um das Thema IT-Sicherheit spezialisiert hat.
Ob es sich um aktuelle Nachrichten, Fachartikel, Blogbeitrรคge, Webinare, Tutorials, oder Tipps & Tricks handelt, TSecurity.de bietet seinen Nutzern einen umfassenden รœberblick รผber die wichtigsten Aspekte der IT-Sicherheit in einer sich stรคndig verรคndernden digitalen Welt.

16.12.2023 - TIP: Wer den Cookie Consent Banner akzeptiert, kann z.B. von Englisch nach Deutsch รผbersetzen, erst Englisch auswรคhlen dann wieder Deutsch!

Google Android Playstore Download Button fรผr Team IT Security



๐Ÿ“š Why JavaScript is a Prototype-based OOP


๐Ÿ’ก Newskategorie: Programmierung
๐Ÿ”— Quelle: dev.to

In object-oriented programming, we can distinguish between two types of languages. Class-based and prototype-based languages.

Class-based languages are centered around classes as the blueprint for creating objects. However, in prototype-based language classes are explicitly excluded, and objects inherit from other objects using prototypes.

Compared to class-based languages like C++ and Java, JavaScript is considered a Prototype-based object-oriented programming language.

This article delves deep into understanding prototype-based object-oriented programming in JavaScript.

By the end of this article you should be able to know:

  • The differences between class-based and prototype-based OOP

  • How inheritance works in class-based programming

  • How inheritance works in prototype-based programming

  • Prototypes and __proto__ properties

  • How to implement prototypal inheritance

Let's get started

Introduction

Whiles working at Netscape, Brendan Eich developed JavaScript as a scripting language to be used in Netscape Navigator, the company's flagship web browser.

Netscape had initially partnered with Sun to incorporate Java programming language into the Navigator. However, the language had some complexities (for instance the JVM consumes a lot of resources, it took several seconds to start a Java applet, etc) that would not appeal to scripters who need to add interactivity to web pages.

To rectify this, Brendan Eich developed JavaScript as a utility language targeted toward scripters and designers.

Netscape's management instructed Brendan Eich not to include advanced features such as classes and modules in JavaScript, to prevent it from appearing to compete with Java.

Because Brendan was not allowed to include classes (which provides a convenient approach for creating objects and inheriting properties and methods), he had to find a way to still maintain the Object-oriented model in JavaScript. He opted for prototypes and implemented prototypal inheritance instead.

Javascript didn't adopt the object-oriented model used by C++ or Java when it was designed because the creator had no time to copy any classical OO model, and Sun didn't want classes included in JS, since JS was supposed to be just a 'sidekick' to Java.

JavaScript is therefore a prototype-based, object-oriented language and uses prototypal inheritance instead of classical inheritance.

Simply put, JavaScript does not have classes, it has prototype objects cloned to produce new objects. Classes are only syntactic sugar for prototypes.

Class-based Programming language

In Class-based programming, objects are built based on the classes. The properties and behavior of an object are defined by a class that serves as a blueprint to create concrete objects.

Consider this analogy, if you were to develop a mobile phone device, you would first design a blueprint that contains all the structure and behavior needed to build the mobile phone. For instance the exterior, operating system, circuit boards, etc, and then build the phone based on that blueprint.

This blueprint is referred to as a class . It is an expandable program code template for creating objects. An object is a real-world entity (for instance a mobile phone).

The blueprint (class) can be extended to build other variations of mobile phone devices ( basic phones, feature phones, and smartphones)

Simply put, in class-based programming, an object must be explicitly created based on a class.

Prototype-based Programming language

Prototype-based programming is a style of object-oriented programming in which classes are not explicitly defined. Inheritance is performed by reusing existing objects that serve as prototypes (objects inherit from other objects through a prototype property).

It permits the creation of an object without first defining its class.

Consider the same analogy of developing a mobile phone device in prototype-based programming.

You first begin by creating the objects ( no blueprints or classes). You assemble the exterior, operating system, circuit boards, etc, and spin up a mobile phone. We can then clone the initial mobile phone and then extend the structure and behavior for the required mobile device (for instance, a smartphone with a wider screen size, touch functionality, sensors, etc).

Using this approach, each mobile phone would be cloned from the generic mobile phone object.

In the world of prototype-based OOP, you build an object and swiftly create "clones" of it compared to the class-based approach, which requires a class to create an object, and then extend the child class to inherit properties and methods from the parent.

Understanding the concept of Prototype-based OOP

In class-based OOP, a class serves as a blueprint for creating objects. A child class will inherit the properties and methods defined in the parent class , and distinct objects are created using the constructor function.

However, in prototype-based OOP, we do not need to define a class to enable us to create object. Objects are created directly.

Because we don't define classes, we need an approach that will enable other objects to inherit properties and methods from the initial object.

There is a hidden property in every object called prototype that enables us to achieve that.

Let's explore this further in the next section.

What is a Prototype?

A prototype is a built-in (hidden) property represented by [[Prototype]] that points to another object. The value pointed at by the [[Prototype]] is casually known as "the prototype of that object"

Consider the example below:

//user object
const user = {
    name: "Emmanuel",
    age: 23,
    city: "Accra"
}

console.log(user)

In the console, you can view the properties of user, alongside the [[Prototype]] (hidden property).

Javascript proto

Because the value of the [[Prototype]] is an Object, we say, it is the prototype of the user object. The Object will also have a prototype property (represented as __proto__ ) including other built-in methods.

This __proto__ is not the same as the hidden [[Prototype]]. It allows us to read and assign details to the [[Prototype]]

Let's expand the Object to investigate

JS Prototype

Prototype chain

Whenever the __proto__ property points to an object . That object will also have a prototype that will also point to another object. In effect, it creates a prototype chain. The prototype chain ends with an object that has a value of null

Javascript prototype

How prototype works

Consider the user object below.

It has three properties: name, age and city.

const user = {
    name: "Emmanuel",
    age: 23,
    city: "Accra"
}

We can access these properties, via the dot (obj.propName ) or bracket (obj['propName']) .

Let's access the name property

user.name
// which returns 
Emmanuel

We instantly have access to the value(Emmanuel)

Now, what happens if we access a property that does not exist in an object?

If we access a property and the object does not directly have that property, the JS engine will look for a property with that name by first searching the [[Prototype]], and because it references an object, it looks for the property in that object.

If it cannot locate the property, that object [[prototype]] will be searched. This search will continue in turns until it a match is found, or reaches the end of the prototype chain.

At the top of the prototype chain is null, at this stage, the property was not found, and undefined is returned.

Prototype chain

The code below illustrates the prototype chain

let person  = {
  eats: true,
  hasLegs: 2,
  walks(){ console.log('I can walk')}
}
//define another object
let man = {
  hasBreast: false,
  hasBeard : true,

}
//set the prototype of man to person object
man.__proto__ = person;
//define a third object
let samuel = {
   age: 23
}
//set the prototype of samuel to man
samuel.__proto__ = man;
//access walk method from samuel
console.log(samuel.walks())
//access hasBeard from samuel
console.log(samuel.hasBeard)
  • We define a person object with eats and hasLegs properties, including a walks method

  • We create a man object and set the prototype of man to the person object using man.__proto__= person

  • We create a specific man samuel and set the prototype of samuel to man using samuel.__proto__ = man

  • Now, we try accessing the samuel.walks() and samuel.hasBeard It is clear from the samuel object that there is no walk method and a hasBeard property.

How then, do we get the output I can walk and true ?

  • Whenever samuel.walks() is called, the JavaScript engine will first search the object samuel for the method.

  • If it is not found, the [[Prototype]] of samuel will be searched.

  • The [[Prototype]] has been set to the object man , hence the JavaScript engine checks the man for the walk method.

  • If it is not found, the [[Prototype]] of man will be searched.

  • Its [[Prototype]] has been set to the person , so we check the person for the walk method.

  • Finally, at the top of the prototype chain, we can locate the method walk in the object person and the JavaScript calls the method even though it wasn't defined in the object samuel.

JavaScript prototype

Let's consider another example. Supposing we want to convert user.name to upper case, we can do it as below:

//convert from Emmanuel to EMMANUEL
const user = {
    name: "Emmanuel",
    age: 23,
    city: "Accra"
}

console.log(user.name.toUpperCase())

When we call the method toUppercase()

  • The JavaScript engine looks for the toUpperCase in the user object

  • If it can't locate it there, it searches the [[prototype]] property of user for toUpperCase

  • Finds it there, and executes the method.

JS prototype

Dimming Properties

Whenever you define a property in an object, and that property has the same name as a property in the [[prototype]], the object's prototype is dimmed and that of the defined property takes precedence.

Consider this example

const myDate = new Date(1999,05,26)
console.log(myDate.getFullYear()) // 1999
//define a method for myDate
myDate.getFullYear = function(){
    console.log('changed the default getFullYear method')
}
myDate.getFullYear()
  • getFullYear() is a built-in method on the myDate object. When executed, it returns the full year

  • We assign a property with the same name to the myDate object, the value of the property is a function that consoles changed the default getFullYear method

  • This approach overwrites the built-in method, this is because the JS engines first check the myDate object for the getFullYear property. Since it finds it there, there is no need to check the object's prototype

This is called "shadowing" the property

Setting the prototype on an object

There two main approaches in setting an object's prototype are:

  • Object.create()

  • Constructor

Let's explore this further.

Using Object.create() to set the prototype

The Object.create() creates a new object and allows you to use existing objects as the new object's prototype.

The syntax is as below:

Object.create(proto) // proto is the existing object

See the example below:

const user = {
    isLoggedIn: false,
    greetUser(){
        console.log(`Howdy ${this.name} !`)
    }
}
//create a new object and set the prototype
const admin = Object.create(user)
  • We defined a user object, with isLoggedIn property and greetUser method.

  • The Object.create() creates a new admin object.

  • We set the prototype of the admin object to the user using the Object.create(user)

Below is the result of logging the admin to the console

JS Prototype

Let's examine the code above:

  • When we first investigate the details of the admin object, it looks empty. However, we notice there exists a [[Prototype]] property. This property is in-built and references the prototype of the admin object.

  • We conclude that the prototype has been set to the existing user object.

We can also assign properties to the admin object. See the example below:

const user = {
  isLoggedIn: false,
    greetUser(){
        console.log(`Howdy ${this.name} !`)
    }  
}

//create an object an set the prototype
const admin = Object.create(user)
console.log(admin)
//assign name property to the admin object
admin.name = "Emmanuel"

The admin now has name property assigned to it. This name property is set on admin but not on user.

Now that we've set the prototype of the object, let's try accessing the greetUser() that was defined in the user object from the admin.

const user = {
  isLoggedIn: false,
    greetUser(){
        console.log(`Howdy ${this.name} !`)
    }  
}

//create an object an set the prototype
const admin = Object.create(user)
console.log(admin)
//assign name property to the admin object
admin.name = "Emmanuel"
//access greetUser from admin 
admin.greetUser()
// output
Howdy Emmanuel !

The output is as below:

JS Prototype

How was it possible to access, the greetUser method when it was not defined in the admn object?

Let's examine this further

  • name is the only visible property in the admin object

  • There is also a hidden [[Prototype]] property, that reference an Object

  • That Object is the existing user we passed to the Object.create() method.

  • As explained, when we access a property on an object, and that property does not exist, we will look at the prototype of the object for the property.

  • In this scenario, the prototype of the object admin has been set to user.

  • In the user prototype, we have access to the greetUser method

  • Now we can call greetUser() on the admin, and the prototype will handle the implementation.

  • This explains why, the admin.greetUser() executes the method even though it was not defined in the admin .

  • Note that, the this keyword used in the user will reference the newly created object ( in this example admin). Hence, this.name references Emmanuel

Using the constructor function to set the prototype

In JavaScript, every function has a prototype property. The prototype enables us to add properties and methods to a constructor function.

Whenever we create an object from the constructor function, the object can inherit the properties and methods from the function's prototype.

Here is an example

//constructor function
function User (name) {
  this.name =name,
  this.age = 34
}

//add greet method to the function's prototype
User.prototype.greet = function(){console.log(`Howdy ${this.name}`)}
//create a new object
const admin = new User("Jonas");
//access the greet method from the admin
console.log(admin.greet()) // Howdy Jonas
  • We define a constructor function User, with name and age properties

  • The User has a prototype property that allows us to assign the greet method.

  • We created an admin object from the User

  • Now, even though greet has not been defined in the admin, it inherits that method from the prototype.

  • This explains why we can call the greet method on the admin object.

New objects created from the constructor function will also inherit the greet method as well as additional properties and methods assigned to the prototype.

Furthermore, if a prototype value is changed, all the new objects will have the updated value.

See the example below:

function User (name) {
  this.name =name,
  this.age = 34
}
//create a new object
const admin = new User("Jonas");

//add greet method to the constructor function 
User.prototype.greet = function(){console.log(`Howdy ${this.name}`)}

//in effect extending the object
console.log(admin.greet())

//add additional method to the prototype 
User.prototype.userAction = function(){console.log(`${this.name} what do you like to learn today`)}

//access the new method  (*)
const user2 = new User('Clement')
user2.userAction() 
//output
Clement what do you like to learn today
//change the prototype property
User.prototype.greet = function(){console.log(`Hi ${this.name}`)}

//verify the update method
user2.greet() // Hi Clement

Understanding the __proto__

We can access the prototype of an object using the obj.__proto__ syntax.

__proto__ is the internal property of an object, pointing to its prototype.

In the example below, we read the prototype of the object user2

console.log(user2.__proto__)

JS Prototype

Reading the prototype with __proto__ is considered outdated and has been deprecated. The current approach is to use the Object.getPrototypeOf(obj)

Object.getPrototypeOf(user2)

We can also set the prototype of an object using the __proto__ .

Take a look at the example below:

const obj = {
  greet: function(){console.log('How are you today')}
}

const obj2 = {

}
//set the prototype of obj2
obj2.__proto__ = obj;

//access the greet method
console.log(obj2.greet())
  • We define an obj with a greet method

  • We define obj2 with is an empty object literal

  • We access the __proto__ of obj2 and assign the details of obj . This will copy all the properties and methods in obj to obj2

  • Henceforth, we can call the greet method on obj2 even though it was not defined there

  • obj2 has inherited the greet method from obj

Using __proto__ is the same thing as using the extends keyword in OOP languages.

The current approach to setting the prototype of an object is to use the Object.setPrototypeOf(obj, proto) . This sets the [[Prototype]] of the obj to what we define in the proto argument.

The example below changes the prototype of the user2 object

//using user2 object created earlier
Object.setPrototypeOf(user2, {changeProto: function(){console.log('changing the prototype')}}); // change the prototype of user2
  • We have changed the prototype of user2 from greet method to changeProto method

  • We can verify the change by reading the prototype using the Object.getPrototypeOf(user2)

The output of the above is as below

Javascript prototype

Importance of prototypes in OOP

A prototype is a flawless approach to defining the OOP model in JavaScript, classes are only syntactic sugar for prototypes.

Whenever we define a class, it is transpiled to a constructor function with an in-built prototype property

Below is an illustration

class User {
 greetUser(){
         console.log('Hello world')
 }
}
//transpiled to 
function User {
  User.prototype.greetUser = function(){ console.log('Hello world')}
}

Prototypal Inheritance

In programming, inheritance occurs when one object is able to access all the properties and methods in another object.

Unlike other languages like C++ and Java which implements classical inheritance, JavaScript implements Prototypal inheritance.

With classical inheritance, the child class extends the parent class to enable it to inherit the properties and methods defined in the parent class. A definite object can then be built from the instance of the class.

However, we don't need to define class when dealing with prototypal inheritance. We define a object with its properties and methods, access the initial object, and extend it using the prototype. This new object will then inherit all the properties and methods defined in the initial object.

Prototypal inheritance is a mechanism involving objects inheriting from any other objects rather than from classes.

Everything we discussed previously made use of the concept of prototypal inheritance. For instance, we had defined an object user with its properties and methods, then new objects we create will inherit the properties and methods defined in the user object

Why are there so many ways to manage Prototype

There are different approaches to managing [[Prototype]] and most often it becomes confusing. How did that happen and why?

The JavaScript language has had prototypal inheritance included in its since its inception. However, ways to manage it have evolved.

  • The prototype property of a constructor function has been the oldest way to create objects with a given prototype.

  • Late 2012, Object.create provided the ability to create objects with a given prototype, however, it lacked the ability to get or set the prototype. To give more flexibility to developers, browsers implemented the __proto__ accessor allowing the user to get or set a prototype.

  • Object.setPrototypeOf and Object.getPrototypeOf were added to the standard in 2015, to handle the same functionality as __proto__. As __proto__ was the de-factor, it was deprecated and pushed to Annex B of the standard, that is: optional for non-browser environments

  • In 2022. it was officially allowed to use __proto__ in object literals {...} but not as a getter/setter (still in Annex B).

Summary

  • In Class-based programming, objects are built based on classes.

  • Prototype-based languages permit the creation of an object without first defining its class.

  • There is a hidden property in every object called prototype that enables us to inherit properties and methods

  • The value pointed at by the [[Prototype]] is casually known as "the prototype of that object"

  • Prototypal inheritance is a mechanism involving objects inheriting from any other objects rather than from classes.

If you have found value in this article, please comment or share it on your social handles. It will be of help to somebody. Follow me on https://twitter.com/emmanuelfkumah for dev tips.

...



๐Ÿ“Œ Javascript - OOP with Javascript


๐Ÿ“ˆ 35.63 Punkte

๐Ÿ“Œ How Marketing Changed OOP In JavaScript


๐Ÿ“ˆ 27.82 Punkte

๐Ÿ“Œ Programming Paradigms in JavaScript: OOP, Functional and Event-Driven


๐Ÿ“ˆ 27.82 Punkte

๐Ÿ“Œ 3 fundamental concepts in Javascript OOP


๐Ÿ“ˆ 27.82 Punkte

๐Ÿ“Œ purl 2.3.2 Prototype Object.prototype code injection


๐Ÿ“ˆ 27.66 Punkte

๐Ÿ“Œ mootools-more 1.6.0 Prototype Object.prototype code injection


๐Ÿ“ˆ 27.66 Punkte

๐Ÿ“Œ jquery-deparam 0.5.1 Prototype Object.prototype code injection


๐Ÿ“ˆ 27.66 Punkte

๐Ÿ“Œ jquery-bbq 1.2.1 Prototype Object.prototype code injection


๐Ÿ“ˆ 27.66 Punkte

๐Ÿ“Œ backbone-query-parameters 0.4.0 Prototype Object.prototype code injection


๐Ÿ“ˆ 27.66 Punkte

๐Ÿ“Œ jquery-sparkle 1.5.2-beta Prototype Object.prototype code injection


๐Ÿ“ˆ 27.66 Punkte

๐Ÿ“Œ merge-deep Library up to 3.0.2 Prototype Object.prototype injection


๐Ÿ“ˆ 27.66 Punkte

๐Ÿ“Œ Why Santa Claus Can't Inherit from Human: A Festive OOP Lesson


๐Ÿ“ˆ 25.85 Punkte

๐Ÿ“Œ Popular jQuery JavaScript library impacted by prototype pollution flaw


๐Ÿ“ˆ 21.64 Punkte

๐Ÿ“Œ Mozilla Firefox up to 1.5.0.3 Javascript Object Prototype access control


๐Ÿ“ˆ 21.64 Punkte

๐Ÿ“Œ Why Is JavaScript So Fast? (aka JavaScript Engines - How Do They Even?)


๐Ÿ“ˆ 21.46 Punkte

๐Ÿ“Œ Introduction to JavaScript: What is JavaScript and Why is it Important for Web Development?


๐Ÿ“ˆ 21.46 Punkte

๐Ÿ“Œ OOP Is Dead, Long Live Data-Oriented Design


๐Ÿ“ˆ 20.01 Punkte

๐Ÿ“Œ OOP CMS BLOG 1.0 Cross Site Request Forgery


๐Ÿ“ˆ 20.01 Punkte

๐Ÿ“Œ [webapps] OOP CMS BLOG 1.0 - Cross-Site Request Forgery (Add Admin)


๐Ÿ“ˆ 20.01 Punkte

๐Ÿ“Œ OOP CMS BLOG 1.0 Cross Site Request Forgery


๐Ÿ“ˆ 20.01 Punkte

๐Ÿ“Œ [webapps] OOP CMS BLOG 1.0 - 'search' SQL Injection


๐Ÿ“ˆ 20.01 Punkte

๐Ÿ“Œ OOP CMS BLOG 1.0 SQL Injection


๐Ÿ“ˆ 20.01 Punkte

๐Ÿ“Œ OOP CMS BLOG 1.0 SQL Injection


๐Ÿ“ˆ 20.01 Punkte

๐Ÿ“Œ #0daytoday #OOP CMS BLOG 1.0 - Cross-Site Request Forgery (Add Admin) Vulnerability [#0day #Exploit]


๐Ÿ“ˆ 20.01 Punkte

๐Ÿ“Œ #0daytoday #OOP CMS BLOG 1.0 - search SQL Injection Vulnerability [webapps #exploits #Vulnerability #0day #Exploit]


๐Ÿ“ˆ 20.01 Punkte

๐Ÿ“Œ PHP OOP: OBJECT ORIENTED PROGRAMMING FOR BEGINNERS + PROJECT


๐Ÿ“ˆ 20.01 Punkte

๐Ÿ“Œ Oops! OOP Is Not What I Thought


๐Ÿ“ˆ 20.01 Punkte

๐Ÿ“Œ OOP CMS BLOG 1.0 Cross Site Request Forgery / SQL Injection


๐Ÿ“ˆ 20.01 Punkte

๐Ÿ“Œ Softwareentwicklung: OOP 2020 - Aufbruch ins Unbekannte


๐Ÿ“ˆ 20.01 Punkte

๐Ÿ“Œ software-architektur.tv live von der OOP-Konferenz


๐Ÿ“ˆ 20.01 Punkte

๐Ÿ“Œ How to Make A Deck of Cards With Python Using Object Oriented Programming (OOP)


๐Ÿ“ˆ 20.01 Punkte

๐Ÿ“Œ Was bedeutet "oop"? Bedeutung und Verwendung


๐Ÿ“ˆ 20.01 Punkte

๐Ÿ“Œ Was ist objektorientierte Programmierung (OOP)?


๐Ÿ“ˆ 20.01 Punkte

๐Ÿ“Œ Python & OOP: So geht die objektorientierte Programmierung


๐Ÿ“ˆ 20.01 Punkte

๐Ÿ“Œ Python OOP Tutorial: How to Create Classes and Objects


๐Ÿ“ˆ 20.01 Punkte











matomo