JavaScript的原型和原型链
原型
全貌

User构造函数实例化了一个User实例,所以User构造函数的prototype原型(对象)==User实例的__proto__隐式原型,它们构成了这样的三角关系。User构造函数本质上是new Function()而来的一个实例,所以User构造函数、Function构造函数和Function原型(对象)之间也有这样的三角关系。Function原型(对象)也是个对象呀,所以是new Object()而来,那么Function原型(对象)是Object构造函数的一个实例,则Function原型(对象)、Object构造函数和Object原型(对象)也构成了这样的三角关系。特殊的点:
Object原型(对象)的隐式原型是null,也就是说Object.prototype.__proto__是nullObject构造函数本质上也是new Function()而来的一个实例,那么,其原型对象就是Function原型(对象),即Object.prototype == Function.prototype- 在JS中,万物皆对象,
Function构造函数本质上也是对象,但它比较特殊,它的隐式原型是它的原型(对象),也就是Function.__proto__ == Function.prototype
构造函数
构造函数和普通函数本质上没什么区别,只不过使用了
new关键字创建对象的函数,被叫做了构造函数。构造函数的首字母一般是大写,用以区分普通函数,当然不大写也不会有什么错误。等价于类class
1 | function Person(name, age) { |
1 | class Person { |
以上两种写法都可以用来创建对象,效果等价。
使用new操作符调用构造函数,做了如下几步操作:
- 创建一个新的对象;
- 将新对象的隐式原型(
_proto_)指向构造函数的原型(对象)(prototype); - 将构造函数的
this指向新对象; - 执行构造函数的代码;
- 如果构造函数返回非空对象,则返回此对象,否则,则返回新建的对象;
构造函数和普通函数在本质上并没有区别,构造函数首字母大写只是一个约定成俗的规范而已。
使用 new 操作符调用普通函数也可以创建实例,所以,正确的说,使用 new 操作符调用函数,可使该函数成为构造函数。直接调用 person 函数的话,由于是全局环境下调用,所以 person 的 this 绑定的是 window 。
原型(对象)(prototype)
在js中,每一个函数类型的数据(构造函数) ,都有一个叫做
prototype的属性,这个属性指向的是一个对象,就是所谓的原型(对象),它是一个对象。对于原型(对象) 来说,它有个constructor属性,指向它的构造函数。
二者互相指

原型(对象)最主要的作用就是用来存放实例对象的 公有属性 和 公有方法。
把这些公有的属性和方法放在原型对象里共享,避免重复创建相同的属性和方法造成浪费:
1 | function Person(name, age) { |
获取对象的(隐式)原型
- Object 对象的一个方法
isPrototypeOf可以确定对象和(隐式)原型是否有关系,console.log(Person.prototype.isPrototypeOf(person1)); // true - Object 对象的一个方法
getPrototypeOf可以获取对象的(隐式)原型,console.log(Object.getPrototypeOf(person1) === Person.prototype); // true
重写对象的(隐式)原型
- Object 对象提供一个方法
setPrototypeOf重写对象(隐式)原型。
1 | let father = { |
- Object 对象提供方法
create可以在创建对象的时候指定对象的(隐式)原型。
1 | let father = { |
遮蔽原型
实例不能重写原型的属性,但是实例可以定义一个属性来遮蔽原型上的同名属性。
Object 的原型提供了一个方法
hasOwnPrototype用于判断属性是在(隐式)原型还是实例上,在实例上,返回true,在原型上,返回false。
1 | let Person = function () {}; |
隐式原型(__proto___)
隐式原型是利用
__proto__属性查找原型,这个属性 指向当前对象的构造函数的原型对象,这个属性是对象类型数据的属性,所以 实例对象可以使用

1 | console.log(per1.__proto__ === Person.prototype); // true |
形象的比喻
- 构造函数$\longrightarrow$雕刻师,其
prototype指向原型(对象) - 原型(对象) $\longrightarrow$设计图/设计原型。它也有
__proto__$\longrightarrow$次稿设计图/设计原型,初稿设计图/设计原型。 最最早的初稿是一张白纸,也就是说Object.prototype.__proto__是null - 通过构造函数
new出来的实例对象$\longrightarrow$一个个雕塑作品,其__proto__指向指向原型(对象)
原型链
简介
原型链的核心就是依赖对象的
__proto__的指向,当自身不存在的属性时,就一层层的扒出创建对象的构造函数,直至到Object时,就没有__proto__指向了。

不仅实例有一个__proto__属性,原型对象也有一个__proto__属性指向它的原型,从中继承方法和属性,一层一层,以此类推,直到Object.prototype = null,s通俗来讲:原型链就是多个对象通过__proto__的方式连接了起来。

instanceof
instanceof就是基于 原型链 判断变量的类型
1 | function myInstanceof(left, right) { |
总结
Object是所有对象的爸爸或者祖先,所有对象都可以通过_proto_找到它;Function是所有函数的爸爸,所有的函数都可以通过_proto_找到它;- 函数的
prototype是一个对象,叫原型(对象),包含一些属性和方法; - 对象的隐式原型
__proto__属性指向其构造函数的原型(对象),__proto__将多个对象和隐式原型连接起来,叫做原型链;












