本文已参与「新人创作礼」活动,一起开启掘金创作之路。
前言
首先我们来了解了解原型和原型链的概念:
- 原型的定义,原型叫
prototype
是函数function
对象的一个属性,它是构造函数(new运算符调用的函数)制造出来的对象的公共祖先,通过构造函数产生的对象可以继承到该原型的属性和对象,原型也是对象。prototype
也称为函数的原型(显示原型); __proto__
(或者[[prototype]]
)实例对象的原型,也成为隐式原型。同时实例对象的隐式原型等于构造函数的显示原型constructor
是让构造函数构造出来的所有的对象都能找到自己的构造器。- 原型链的定义:将原型以链表的方式连接起来,就形成了原型链,访问顺序按链表的顺序依次访问。
- 两者的区别:对象的原型(
__proto__
)与构造函数的原型(prototype)属性之间性质不一样。前者是每个实例上都有的属性,后者是构造函数的属性。
原型
- 首先,我们先来见识见识原型。
//person.prototype ---原型
Person.prototype.name = 'weige'
function Person(){
this.name = 'wn'
}
var person = new Person()
console.log(person);
如图所示,我们将构造函数
Person
的原型浏览器上打印,可以清楚地看到原型的‘庐山真面目’。在上面这段代码中,我们向原型添加了两个name
属性,其中用Person.prototype
显示原型的方法添加到了person
的隐式原型。用this.name
的方法就直接添加到了Person
对象上。同时我们还可以看到原型的构造器函数constructor
,记录着构造出的Person
函数的显式原型。
- 接下来,我们来聊聊隐式原型和显示原型。
Person.prototype.name = 'wn'
function Person(){
}
var person = new Person()
console.log(person.__proto__);
如图所示,我们构造了一个
Person
函数,我们向函数Person
的显式原型中添加一个属性name
且值为wn
,现在我们去直接打印person
的隐式原型。我们在person
的隐式原型中看到{name:'wn'}
,为什么我们向对象的显示原型添加属性,却没出现在Person
对象中,而出现在perosn
的隐式原型中呢。这时候我们应该这么认为“实例对象隐式原型等于构造函数显示原型
”。
- 在了解完原型后,我们来看看原型的基本用法
//增
function Person(){}
Person.prototype.lastname ='pan'
//删
function Person(){}
Person.prototype.lastname ='pan'
delete Person.prototype.lastName
//改
function Person(){}
Person.prototype.lastname ='pan'
Person.prototype.lastname ='zhang'
//查
function Person(){}
Person.prototype.lastname ='pan'
var person = new Person()
console.log(person.lastname);
原型的基本用法为‘增删改查’,和对象的用法一样,但是要注意的一点原型‘增删改查’是对构造函数的显式原型prototype进行操作,将键值对增加到实例对象的隐式原型中。
原型链
在了解完原型后,我们再来看看原型链是怎样的呢?那我们就上图来分析分析吧。
想要理解原型链,我们只要看懂这张图。下面我来带大家分析分析。
首先我们构造function Foo()
函数,函数Foo的显式原型为Foo.prototype
,函数Foo的隐式原型就是_proto_
;
(实例对象的隐式原型 === 构造函数的显式原型。)
而构造函数Foo
的隐式原型( __ proto __ )
指向Object.prototype
,因为所有的构造函数的显示对象的隐式原型都会指向对象Object
。
(所有function函数是通过Function函数构造出来的)
那么下面我们看看为什么function Function()
和Function.prototype
会形成环装结构,首先因为Function
是一个函数,函数就是一种对象,就会有隐式原型属性和显示原型属性。既然是函数,那么它一定是被Function
创建。所以function Function()
的显式原型一定是Function.prototype
,那接下来就是理解function Function()
的隐式原型还是Function.prototype
了。
既然是函数是被Function
函数构造出来的,那么我们也可以把function Function()
看成一个实例对象,实例对象的隐式原型不就是构造函数Function
的显式原型吗?Function.prototype
也是一个对象的显示原型,所以它的隐式原型也就自然指向Object.prototype
最后因为对象也是被构造函数创建出来的,所以function Object()
的隐式原型就是构造函数的显式原型Function.prototype
,当然函数对象的显式原型就是Object.prototype
,构造函数new出来的实例对象的隐式原型就Object.prototype
; 因为万物皆对象,所以Object.prototype
是最顶端了,它的隐式原型就指向了null
。