JavaScript中的原型

Stella981
• 阅读 671

JavaScript中的原型

Photo by Dlanor S on Unsplash

In this post, we will discuss what are prototypes in JavaScript, how they help JavaScript in achieving the concepts of Object-Oriented Programming.

In the previous post, we had learned various ways of creating objects in JavaScript. One of the ways to create objects in JavaScript is using the constructor function.

Problem with creating objects with the constructor function:

Consider the constructor function below:

Let’s create objects person1 and person2 using the Human constructor function:

var person1 = new Human("Virat", "Kohli"); var person2 = new Human("Sachin", "Tendulkar");

On executing the above code, the JavaScript engine will create two copies of the constructor function, each for person1 and person2.

JavaScript中的原型

i.e. every object created using the constructor function will have its own copy of properties and methods. It doesn’t make sense to have two instances of function fullName that do the same thing. Storing separate instances of function for each object results in wastage of memory. We will see as we move forward, how we can solve this issue.

Prototypes

When a function is created in JavaScript, the JavaScript engine adds a prototype property to the function. This prototype property is an object (called a prototype object) that has a constructor property by default. The constructor property points back to the function on which prototype object is a property. We can access the function’s prototype property using functionName.prototype.

JavaScript中的原型

As shown in the above image, Human constructor function has a prototype property that points to the prototype object. The prototype object has a constructor property that points back to the Human constructor function. Let’s see an example below:

console.log(person1);

JavaScript中的原型

To access the prototype property of the Human constructor function, use the below syntax:

console.log(Human.prototype)

JavaScript中的原型

As seen from the above image prototype property of the function is an object (prototype object) with two properties:

  1. constructor property which points to Human function itself
  2. __proto__ property: We will discuss this while explaining inheritance in JavaScript

Creating an object using the constructor function

When an object is created in JavaScript, JavaScript engine adds a __proto__ property to the newly created object which is called dunder proto. dunder proto or __proto__ points to the prototype object of the constructor function.

JavaScript中的原型

As shown in the above image, the person1 object which is created using the Human constructor function has a dunder proto or __proto__ property which points to the prototype object of the constructor function.

//Create an object person1 using the Human constructor function var person1 = new Human("Virat", "Kohli");

JavaScript中的原型

As can be seen from the above image, both person1’s dunder proto or __proto__ property and Human.prototype property is equal. Let’s check if they point at the same location using === operator

Human.prototype === person1.__proto__ //true

This shows that person1’s dunder proto property and Human.prototype are pointing to the same object.

Now, let’s create another object person2 using the Human constructor function

var person2 = new Human("Sachin", "Tendulkar"); console.log(person2);

JavaScript中的原型

Above console output shows that even _person2’s_ dunder proto property is equal to the Human.prototype property and they point to the same object.

Human.prototype === person2.__proto__ //trueperson1.__proto__ === person2.__proto__ //true

Above statement proves that the person1’s and person2’s dunder proto properties point to Human constructor function’s prototype object.

JavaScript中的原型

The prototype object of the constructor function is shared among all the objects created using the constructor function.

Prototype Object

As a prototype object is an object, we can attach properties and methods to the prototype object. Thus, enabling all the objects created using the constructor function to share those properties and methods.

The new property can be added to the constructor function’s prototype property using either the dot notation or square bracket notation as shown below:

JavaScript中的原型

name and age properties have been added to the Human prototype

Example

Let’s analyze what happened when we did console.log(person.name). Let’s check if the person object has a name property

console.log(person1);

JavaScript中的原型

As we can see that person1 object is empty and it does not have any property except its dunder proto property. So how does the output of console.log(person.name) was Ashwin?

When we try to access a property of an object, the JavaScript engine first tries to find the property on the object, if the property is present on the object it outputs its value. But, if the property is not present on the object then it tries to find the property on the prototype object or dunder proto of the object. If the property is found the value is returned else JavaScript engine tries to find the property on the dunder proto of the object. This chain continues until the dunder proto property is null. In these cases, the output will be undefined.

So, when person1.name is called, JavaScript engine checks if the property exists on the person1 object. In this case, name property was not on the person1’s object. So, now JavaScript engine checks if the name property exists on the dunder proto property or the prototype of the person1’s object. In this case, name property was there on the dunder proto property or the prototype of person1’s object. Hence, the output was returned Ashwin.

Let’s create another object person2 using the Person constructor function.

var person2 = new Person(); //Access the name property using the person2 object console.log(person2.name)// Output: Ashwin

Now, let’s define a property name on the person1 object

person1.name = "Anil" console.log(person1.name)//Output: Anil console.log(person2.name)//Output: Ashwin

Here person1.name outputs “Anil”. As mentioned earlier, the JavaScript engine first tries to find the property on the object itself. In this case, name property is present on the object person1 itself, hence JavaScript engines outputs the value of name property of person1.

In the case of person2, the name property is not present on the object. Hence, it outputs person2’s prototype object’s property name.

Problems with the prototype

As prototype object is shared among all the objects created using the constructor function, its properties and methods are also shared among all the objects. If an object A modifies a property of the prototype having primitive value, other objects will not get affected by, as object A will create a property on its objects as shown below.

Here (line 1 and 2), both _person1_ and _person2_ does not have _name_ property, hence they access the prototypes _name_ property and hence the output is same for both.

When person1 want to have a different value for the name property, it creates a name property on its object.

Consider another example to display the issue with prototypes when the prototype object contains a property of reference type

In the above example, person1 and person2 point to the same friends' array of the prototype object. person1 modifies friends property by adding another string in the array.

As friends' array exists on Person.prototype, not on person1, the changes made in the friend’s property by person1 object is reflected on person2.friends also (which points to the same array).

If the intention is to have an array shared by all instances, then this outcome is okay. But here this was not the case.

Combine Constructor/Prototype

To solve the problems with the prototype and the problems with the constructor, we can combine both the constructor and function.

  1. Problem with the constructor function: Every object has its own instance of the function
  2. Problem with the prototype: Modifying a property using one object reflects the other object also

To solve both problems, we can define all the object-specific properties inside the constructor and all shared properties and methods inside the prototype as shown below:

Here as we have wanted each object to have their own name, age, and friends property. Hence, we have defined these properties inside the constructor using this. However, as sayName is defined on the prototype object, it will be shared among all the objects.

In the above example, the friend’s property of person2 did not change on changing the friends' property of person1.

JavaScript中的原型

If you enjoyed the article and want updates about my new article, please follow me on medium and on twitter @happyrupesh123

点赞
收藏
评论区
推荐文章
blmius blmius
2年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Jacquelyn38 Jacquelyn38
2年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Stella981 Stella981
2年前
Opencv中Mat矩阵相乘——点乘、dot、mul运算详解
Opencv中Mat矩阵相乘——点乘、dot、mul运算详解2016年09月02日00:00:36 \牧野(https://www.oschina.net/action/GoToLink?urlhttps%3A%2F%2Fme.csdn.net%2Fdcrmg) 阅读数:59593
Stella981 Stella981
2年前
Android So动态加载 优雅实现与原理分析
背景:漫品Android客户端集成适配转换功能(基于目标识别(So库35M)和人脸识别库(5M)),导致apk体积50M左右,为优化客户端体验,决定实现So文件动态加载.!(https://oscimg.oschina.net/oscnet/00d1ff90e4b34869664fef59e3ec3fdd20b.png)点击上方“蓝字”关注我
Wesley13 Wesley13
2年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
2年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
2年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Stella981 Stella981
2年前
Google地球出现“无法连接到登录服务器(错误代码:c00a0194)”解决方法
Google地球出现“无法连接到登录服务器(错误代码:c00a0194)”解决方法参考文章:(1)Google地球出现“无法连接到登录服务器(错误代码:c00a0194)”解决方法(https://www.oschina.net/action/GoToLink?urlhttps%3A%2F%2Fwww.codeprj.com%2Fblo
Wesley13 Wesley13
2年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
3个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这