【Javascript】从原型到原型链

我心飞翔 分类:javascript

构造函数创建对象

function Person() {}
let per = new Person()
per.name = '旧时光'
console.log(per)   //  { name: '旧时光' }
 

上面的例子中Person是一个构造函数,而per是这个构造函数的实例

prototype

什么是原型:每一个JavaScript对象(null除外)在创建的时候就会关联另外一个对象,这个对象就是原型,且每个对象都会从原型中继承属性,如下面的例子

function Person(){}
Person.prototype.name = '旧时光'
const person1 = new Person()
const person2 = new Person()
console.log(person1.name)   //旧时光
console.log(person2.name)   //旧时光
 

如代码所示,person1和person2都继承了Person的属性name。

构造函数的prototype属性指向了一个对象,而这个对象就是调用该构造函数创建实例的原型,也就是实例person1和person2的原型。

下图就展示了实例的构造函数以及实例原型之间的关系

image.png
这张图使用了Person.prototype来表示了实例的原型,那实例和原型之间又有什么关系,接下来可以看另外一个属性__proto__

proto

每一个JavaScript对象都有一个属性__proto__属性,这个属性会指向该对象的原型

function Person(){}
const person = new Person()
console.log(person.__proto__ === Person.prototype)  // true
 

于是乎实例、原型、构造函数三者就有了下面的关系
image.png
实例对象和构造函数都有属性可以指向原型,那原型有没有属性可以指向构造函数或者实例?

constructor

原型没有属性可以指向实例,但是有属性可以指向构造函数

每一个原型都有一个constructor属性可以指向构造函数

function Person(){}
console.log(Person.prototype.constructor === Person)  // true
 

image.png
通过上面关系可以得出:

function Person(){}
var person = new Person();

Person.prototype === person.__proto__
Person.prototype.constructor === Person
Object.getPrototypeOf(person) === Person.prototype
 

实例和原型

当读取实例的属性时,如果在实例上没有找到该属性,则会查找与实例对象关联的原型中的属性,如果没找到就会继续找原型的原型,一直找到最顶层为止

function Person(){}
Person.prototype.name = '旧时光'

const person = new Person()
person.name = '十一'
console.log(person.name)  //十一

delete person.name
console.log(person.name)  //旧时光
 

如上面代码展示,实例person上有属性name时,这是读取person的name属性是‘十一’,当把实例person的属性name删除后,再去访问name属性,此时实例person上已经没有了name属性,因此会向上找,在原型中找到了name属性'旧时光'

原型的原型

原型也是一个对象,原型对象就是通过Object构造函数生成的,结合之前将的实例的__proto__属性指向构造函数的prototype,因此:

image.png

原型链

Object.prototype.__proto__ === null
 

所以Object.prototype.__proto__为null和Object.prototype没有原型是一个意思
所以原型查找查到Object.prototype也就到头了

image.png
如图,原型链就是途中蓝色的线

描述就是:查找一个对象的属性时,如果在该对象上没有要查找的属性,则会向对象的原型中查找,如果原型中也没有,则会在原型中的原型查找,如果还没有找到,则会继续往上找,直到找到Object.prototype,中间这条原型穿起来的链就叫原型链

补充

实例可以访问原型上的属性是继承么?
继承意味着拷贝操作,然而这里实例访问原型的属性并不是拷贝,仅仅是对象间建立了一个链接,可以通过实例来访问到原型的属性,因此使用 委托 更贴切

回复

我来回复
  • 暂无回复内容