javascript原型和原型链特点,javascript的原型,原型链,有什么特点?
本文为大家带来一些关于javascript的知识,包括关于“原型”和“原型链”的相关问题,包括构造函数、原型对象原型、对象原型等等。下面就一起来看看吧,希望对你有帮助。
【相关推荐:javascript视频教程,web前端】
什么是原型?原型是我们在JS基础学习中没有提到的概念。原型是一个统称,主要包括原型对象 (prototype) 、对象原型 (__proto__)、原型链、等。据统计,这些概念也是面试中经常被问到的。本文将带你了解和掌握prototype的相关知识,让你不再迷茫。
一:构造函数
我们学习了很多面向对象的语言,比如java c等。但是JavaScript是个例外。在ES6之前,没有类的概念。那么在那之前我们是如何创造物体的呢?原来在ES6之前,我们是用构造函数 来创建实例化对象的。构造函数是一个特殊的函数,包含了对象的共同特征,所以和new一起使用是有意义的。
构造函数的注意事项:
构造函数名的首字母要大写构造函数要配合 new 一起使用
1.1 构造函数使用方法
脚本
函数Animal(name,age){ //构造函数名的第一个字母大写。
this.name=name
this.age=年龄;
this.eat=function(){
Console.log(我在吃饭);
}
}
Var=newAnimal(王采,3) //创建用于New
console . log(dog . name);
console . log(dog . age);
狗.吃()
/脚本
1.2 构造函数new的执行过程
new 有以下执行过程:
新建,将创建一个空对象。构造函数中的this指向这个空对象,构造函数中的代码给这个空对象赋值。添加属性的方法返回这个对象
1.3 实例成员与静态成员
实例成员:
实例成员是在旁观者内部用这个添加的成员。实例成员只能通过实例化的对象访问,但不能通过构造函数名访问脚本。
功能动物(姓名、年龄){
this.name=name
this.age=年龄;
}
Var dog=新动物(“王采”,3)
console . log(dog . name);
console . log(animal . name);
/脚本
静态成员:
静态成员是由构造函数本身创建的成员。静态成员只能通过构造函数名来访问,而不能通过实例化对象来访问。
功能动物(姓名、年龄){
this.name=name
this.age=年龄;
}
Var dog=新动物(“王采”,3)
Animal.color=黑色
console . log(animal . color);
console . log(dog . color);
/脚本
二: 原型对象 prototype
2.1 为什么有原型对象
在开始描述原型对象是什么之前,我们先来说明一个案例,还是刚才的动物类。我们创建了几个实例化对象,比较了输出它们的实例化对象的两种方法,发现输出的是false,即两者的复杂数据类型的地址不同。原因是什么?
脚本
功能动物(姓名、年龄){
this.name=name
this.age=年龄;
this.eat=function(){
Console.log(我在吃饭);
}
}
Var dog=新动物(“王采”,3)
Var=新动物(咪咪,3)
Var pig=新动物(哼,3)
鱼=新动物(“咕噜”,3)
Var sheep=新动物(“咩咩”,3)
console . log(dog . eat==cat . eat);
/脚本
在创建实例化对象的过程中,新的进程会先创建一个新的对象,但是复杂的数据类型会开辟一个空间来存储(对象,方法),这个空间就是造成了构造函数内同样的方法被开辟了无数块内存,造成了内存的极度浪费。
2.2 原型对象的使用
constructor的原型是constructor中的一个属性,它的属性是一个对象的指针,对象中存储了一个公共方法。当通过构造函数创建实例化对象时,可以公开使用该对象中的方法,因此不必为多个相同的复杂数据类型打开多个重复的内存空间。为了解决上面提到的内存浪费问题,也可以直接调用原型对象。
上述案例解决方案:
解决方案我们使用prototype对象存储公共方法,让实例化的对象调用方法,比较两个对象的地址是否相同。
脚本
功能动物(姓名、年龄){
this.name=name
this.age=年龄;
}
animal . prototype . eat=function(){
Console.log(我在吃饭);
}
Var dog=新动物(“王采”,3)
Var=新动物(咪咪,3)
狗.吃()
cat.eat()
console . log(dog . eat==cat . eat);
/script我们发现不仅这个方法被成功调用,而且两个调用方法的地址也是相同的,证明了其常见的复杂数据类型只开辟了一个内存空间,减少了以前在构造函数中编写公共方法时的资源浪费。
三:对象原型 __proto__
3.1 什么是对象原型?
对象原型__proto__的作用是让你明白一个问题:为什么给构造函数的prototype属性添加的方法,实例化对象却可以使用?这是因为每个对象都有一个__proto__属性(注意前后有两个下划线),这个属性也是指向其对应构造函数的prototype对象原型的指针。
或者可以理解为:
原型对象prototype 等价于 对象原型 __proto__
3.2 关于对象原型__proto__的注意点
我们要注意的是,对象prototype __protp__的作用只是提供一个在prototype对象中查找内容的方向。我们不需要使用它,只要记住它指向对应构造函数的prototype对象原型就可以了。
方法的查找原则:
首先去找实例化自身的构造函数身上有没有目标方法,有则调用如果自身构造函数身上没有,由于因为对象自身有属性__protp__,其指向构造函数的原型对象prototype,则会去找原型对象身上有没有该方法
四:构造函数 constructor
4.1 为什么 constructor 也叫构造函数
对象原型__proto__和构造函数的原型对象原型上有一个构造函数属性。它之所以被称为构造函数,是因为这个属性指向相应的构造函数本身,它主要用于
打印二者的constructor属性:
脚本
功能动物(姓名、年龄){
this.name=name
this.age=年龄;
}
animal . prototype . eat=function(){
Console.log(我在吃饭);
}
Var dog=新动物(“王采”,4)
console.log(狗。__proto__。建造师);
console . log(animal . prototype . constructor);
/脚本
我们发现打印出来结果确实为构造函数本身
4.2 手动返回 constructor 的情况
通常情况下,我们需要手动返回构造函数指向的对象。例如,当多个公共方法作为对象存储在构造函数的prototype对象中时,将发生以下情况:
脚本
功能动物(姓名、年龄){
this.name=name
this.age=年龄;
}
Animal.prototype={
eat:function(){
Console.log(我在吃饭);
},
run:function(){
Console.log(我在跑);
}
}
var dog=新动物(“旺仔”,3)
console . log(animal . prototype . constructor);
console.log(狗。__proto__。建造师);
/脚本
我们发现找不到对应的构造函数,这是由于我们将方法添加到其原型对象的方式造成的。这个钱我们是以a .的方式添加的,是基于原创的,不会覆盖内部原创内容。但是我们用=的方法作为对象添加,其实就是一个赋值的过程,原来的内容也被覆盖了,导致prototype里面原来的构造函数方法被覆盖了。
这时就需要我们手动返回 constructor 来找到返回的是哪个的构造函数
脚本
功能动物(姓名、年龄){
this.name=name
this.age=年龄;
}
Animal.prototype={
构造者:动物,
eat:function(){
Console.log(我在吃饭);
},
run:function(){
Console.log(我在跑);
}
}
var dog=新动物(“旺仔”,3)
console . log(animal . prototype . constructor);
console.log(狗。__proto__。建造师);
/脚本
这样就可以成功得到它的构造函数指向哪个构造函数。
其格式为:
constructor : 构造函数名 【相关推荐:javascript视频教程,web前端】以上是对JavaScript“原型”和“原型链”的详细介绍。更多请关注我们的其他相关文章!
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。