原型和原型链详细讲解

news/2024/11/17 23:57:03/

目录

一、构造函数

二、原型对象

三、原型链

四、函数也是一种对象

 五、总结


一、构造函数

构造函数、普通函数区别,使用new关键字创建对象的函数叫构造函数。构造函数的首字母一般是大写,用以区分普通函数。

function Person(name, age) {this.name = name;this.age = age;this.species = '人类';this.say = function () {console.log("Hello");}
}let per1 = new Person('xiaoming', 20);

二、原型对象

在js中,每一个函数类型的数据,都有一个叫做prototype的属性,这个属性指向的是一个对象,就是所谓的原型对象。

 对于原型对说,它有个constructor属性,指向它的构造函数。

 

打印原型对象:

 

原型对象作用:存放实例对象公有属性公有方法

在上面那个例子里species属性和say方法对于所有实例来说都一样,放在构造函数里,那每创建一个实例,就会重复创建一次相同的属性和方法,显得有些浪费。这时候,如果把这些公有的属性和方法放在原型对象里共享,就会好很多。

function Person(name, age) {this.name = name;this.age = age;
}Person.prototype.species = '人类';
Person.prototype.say = function () {console.log("Hello");
}let per1 = new Person('xiaoming', 20);
let per2 = new Person('xiaohong', 19);console.log(per1.species); // 人类 
console.log(per2.species); // 人类per1.say(); // Hello
per2.say(); // Hello

打印是原型对象:

 

这里的species属性、say方法不是实例对象的,为什么可以直接用点运算符访问?

这是因为在js中,对象里没有面对应的属性、方法  ==>  构造函数的原型对象。

有就会返回属性值或调用方法。有时候,我们会用per1.constructor查看对象的构造函数:

console.log(per1.constructor); // Person()

这个constructor是原型对象的属性,在这里能被实例对象使用,原因就是上面所说的。那如果原型对象上也没有找到想要的属性呢?这就要说到原型链了。

三、原型链

1. 显示原型

显示原型就是利用prototype属性查找原型,只是这个是函数类型数据的属性。 例如: 构造函数.prototype   ==> Person .prototype

2. 隐式原型

隐式原型是利用__proto__属性查找原型,这个属性指向当前对象的构造函数的原型对象,这个属性是对象类型数据的属性。例如:

实例.__proto__  ==>  per1.__proto__

console.log(per1.__proto__ === Person.prototype); // true
console.log(per2.__proto__ === Person.prototype); // true

根据上面,就可以得出constructor、prototype和__proto__之间的关系了:

 3. 原型链

既然这个是对象类型的属性,而原型对象也是对象,那么原型对象就也有这个属性,但是原型对象的__proto__又是指向哪呢?

我们来分析一下,既然原型对象也是对象,那我们只要找到对象的构造函数就能知道__proto__的指向了。而js中,对象的构造函数就是Object(),所以对象的原型对象,就是Object.prototype。既然原型对象也是对象,那原型对象的原型对象,就也是Object.prototype。不过Object.prototype这个比较特殊,它没有上一层的原型对象,或者说是它的__proto__指向的是null。

所以上面的关系图可以拓展成下面这种:

 

到这里,就可以回答前面那个问题了,如果某个对象查找属性,自己和原型对象上都没有,那就会继续往原型对象的原型对象上去找,这个例子里就是Object.prototype,这里就是查找的终点站了,在这里找不到,就没有更上一层了(null里面啥也没有),直接返回undefined。

可以看出,整个查找过程都是顺着__proto__属性,一步一步往上查找,形成了像链条一样的结构,这个结构,就是原型链。所以,原型链也叫作隐式原型链。

正是因为这个原因,我们在创建对象、数组、函数等等数据的时候,都自带一些属性和方法,这些属性和方法是在它们的原型上面保存着,所以它们自创建起就可以直接使用那些属性和方法。

四、函数也是一种对象

函数在js中,也算是一种特殊的对象,所以,可以想到的是,函数是不是也有一个__proto__属性?答案是肯定的,既然如此,那就按上面的思路,先来找找函数对象的构造函数。

在js中,所有函数都可以看做是Function()的实例,而Person()和Object()都是函数,所以它们的构造函数就是Function()。Function()本身也是函数,所以Function()也是自己的实例,听起来既怪异又合理,但是就是这么回事。

console.log(Person.constructor === Function); // true
console.log(Object.constructor === Function); // true
console.log(Function.constructor === Function); // true

既然知道了函数的构造函数,那么函数的__proto__指向我们也就知道了,就是Function.prototype。

console.log(Person.__proto__ === Function.prototype); // true
console.log(Object.__proto__ === Function.prototype); // true
console.log(Function.__proto__ === Function.prototype); // true

根据这几个结论,我们就能拓展出一张更大的关系图了:

在这里插入图片描述

 五、总结

1、构造函数是使用了new关键字的函数,用来创建对象,所有函数都是Function()的实例
2、原型对象是用来存放实例对象的公有属性和公有方法的一个公共对象,所有原型对象都是Object()的实例
3、原型链又叫隐式原型链,是由__proto__属性串联起来,原型链的尽头是Object.prototype


http://www.ppmy.cn/news/484820.html

相关文章

硬核!原型和原型链详解

前言 我是歌谣 知其然知其所以然 人人都有一个大厂梦 希望通过自己的一个总结分享可以给予大家带来帮助和提升。 本期知识点 原型和原型链 目标 1理解原型和原型链 2理解构造函数 3理解构造函数 原型和原型链之间的关系 引用类型都是对象 基本数据类型和引用数据类型可以看下…

【原型和原型链】什么是原型和原型链

一、原型 ①所有引用类型都有一个__proto__(隐式原型)属性,属性值是一个普通的对象 ②所有函数都有一个prototype(原型)属性,属性值是一个普通的对象 ③所有引用类型的__proto__属性指向它构造函数的prototype var a [1,2,3]; a.__proto__ Array.pro…

原型链详解

什么是原型链 原型链就是顺着__proto__所在的一条链子,这样说可能不是很好理解,下面来看例子你就会理解。 需要了解 1.a.__proto__和 a.prototype都称做为a的原型。 2.Object.prototype是原型链的顶端。 3.如果 a是由b实例化出来的,则有关…

(二)原型和原型链

文章目录 一、原型和原型链1.构造函数2.为什么要一个原型对象?3.两个属性:prototype与__proto__4.原型链 二、new和Object.create的区别1.Object.create的使用2.二者区别 一、原型和原型链 在接触原型与原型链中,我产生了以下几个疑问&#…

最详尽的 JS 原型、js原型链终极详解(第二篇)

四. proto JS 在创建对象(不论是普通对象还是函数对象)的时候,都有一个叫做__proto__ 的内置属性,用于指向创建它的构造函数的原型对象。 对象 person1 有一个 __proto__属性,创建它的构造函数是 Person,构…

原型及原型链详解

(首先先大致的介绍一下什么是原型与原型链及相关术语,以便初学者有个大概的了解) 原型:被用于复制现有实例来生成新实例的函数 (这里补充一个设计模式为原型模式,即用原型实例指定创建对象的种类&#xff…

产品思维的核心要素

产品思维的关键词 如果说用几个关键词来总结 “产品思维” ,我会用以下几个关键词来概括它,分别是:"4高"、"1深"、"3广" ,具体怎么理解,我们接下来一个一个的说。 4高 先来看一看 4高…

elasticsearch 创建索引模版template

添加索引代码如下: PUT _template/redsmg-chandemo {"order" : 2,"index_patterns" : ["redsmg-chandemo_*"],"mappings" : {"doc" : {"dynamic_templates" : [{"string_as_num" : {"…