JavaScript中的原型

Stella981
• 阅读 446

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

点赞
收藏
评论区
推荐文章
秃头王路飞 秃头王路飞
4个月前
webpack5手撸vue2脚手架
webpack5手撸vue相信工作个12年的小伙伴们在面试的时候多多少少怕被问到关于webpack方面的知识,本菜鸟最近闲来无事,就尝试了手撸了下vue2的脚手架,第一次发帖实在是没有经验,望海涵。languageJavaScript"name":"vuecliversion2","version":"1.0.0","desc
浅梦一笑 浅梦一笑
4个月前
初学 Python 需要安装哪些软件?超级实用,小白必看!
编程这个东西是真的奇妙。对于懂得的人来说,会觉得这个工具是多么的好用、有趣,而对于小白来说,就如同大山一样。其实这个都可以理解,大家都是这样过来的。那么接下来就说一下python相关的东西吧,并说一下我对编程的理解。本人也是小白一名,如有不对的地方,还请各位大神指出01名词解释:如果在编程方面接触的比较少,那么对于软件这一块,有几个名词一定要了解,比如开发环
技术小男生 技术小男生
4个月前
linux环境jdk环境变量配置
1:编辑系统配置文件vi/etc/profile2:按字母键i进入编辑模式,在最底部添加内容:JAVAHOME/opt/jdk1.8.0152CLASSPATH.:$JAVAHOME/lib/dt.jar:$JAVAHOME/lib/tools.jarPATH$JAVAHOME/bin:$PATH3:生效配置
光头强的博客 光头强的博客
4个月前
Java面向对象试题
1、请创建一个Animal动物类,要求有方法eat()方法,方法输出一条语句“吃东西”。创建一个接口A,接口里有一个抽象方法fly()。创建一个Bird类继承Animal类并实现接口A里的方法输出一条有语句“鸟儿飞翔”,重写eat()方法输出一条语句“鸟儿吃虫”。在Test类中向上转型创建b对象,调用eat方法。然后向下转型调用eat()方
刚刚好 刚刚好
4个月前
css问题
1、在IOS中图片不显示(给图片加了圆角或者img没有父级)<div<imgsrc""/</divdiv{width:20px;height:20px;borderradius:20px;overflow:h
blmius blmius
1年前
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
小森森 小森森
4个月前
校园表白墙微信小程序V1.0 SayLove -基于微信云开发-一键快速搭建,开箱即用
后续会继续更新,敬请期待2.0全新版本欢迎添加左边的微信一起探讨!项目地址:(https://www.aliyun.com/activity/daily/bestoffer?userCodesskuuw5n)\2.Bug修复更新日历2.情侣脸功能大家不要使用了,现在阿里云的接口已经要收费了(土豪请随意),\\和注意
晴空闲云 晴空闲云
4个月前
css中box-sizing解放盒子实际宽高计算
我们知道传统的盒子模型,如果增加内边距padding和边框border,那么会撑大整个盒子,造成盒子的宽度不好计算,在实务中特别不方便。boxsizing可以设置盒模型的方式,可以很好的设置固定宽高的盒模型。盒子宽高计算假如我们设置如下盒子:宽度和高度均为200px,那么这会这个盒子实际的宽高就都是200px。但是当我们设置这个盒子的边框和内间距的时候,那
艾木酱 艾木酱
3个月前
快速入门|使用MemFire Cloud构建React Native应用程序
MemFireCloud是一款提供云数据库,用户可以创建云数据库,并对数据库进行管理,还可以对数据库进行备份操作。它还提供后端即服务,用户可以在1分钟内新建一个应用,使用自动生成的API和SDK,访问云数据库、对象存储、用户认证与授权等功能,可专
Wesley13 Wesley13
1年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
helloworld_28799839 helloworld_28799839
4个月前
常用知识整理
Javascript判断对象是否为空jsObject.keys(myObject).length0经常使用的三元运算我们经常遇到处理表格列状态字段如status的时候可以用到vue