JavaScript温故而知新——原型和原型链

1、原型模式

咱们建立的每个函数都有一个prototype(原型)属性,这个属性指向的是经过调用构造函数来建立出来的对象实例原型对象,这个原型对象可让全部对象实例共享它所包含的属性和方法。bash

function Person () {
    
}
Person.prototype.name = "xiao";
Person.prototype.sayName = function () {
    alert('this.name')
}
var person1 = new Person();
var person2 = new Person();
person1.sayName()  // "xiao"
console.log(person1.name == person2.name)   // "true"
复制代码

上面的例子当中咱们建立了一个构造函数Person,并经过它的prototype属性在它的原型对象中定义了name属性并赋值,而后经过调用构造函数Person实例化出来两个对象实例,经过打印出来的值咱们能够得知,person1person2共享了原型对象中的属性和方法。闭包

构造函数,原型对象和对象实例的关系

咱们知道每一个函数都有一个prototype属性指向函数的原型对象。在默认状况下,全部原型对象都有一个constructor(构造函数)属性,这个属性指向了prototype属性所在的函数,好比前面的例子中,Person.prototype.constructor就指向Person
另外,当调用构造函数建立一个新实例后,该实例的内部将包含一个__porto__属性(仅在Firefox、Safari、Chrome中支持),这个属性指向的就是构造函数的原型对象。由此咱们能够得出如下图示的结论:app

经过代码来验证:函数

# 实例和原型对象之间的关系
console.log(person.__proto__ == Person.prototype) // true

# 也能够经过isPrototypeOf()和ES5中的Object.getPrototypeOf()方法来判断
console.log(Person.prototype.isPrototypeOf(person1)) // true
console.log(Object.getPrototypeOf(person) === Person.prototype) // true

# 原型对象和构造函数的关系
console.log(Person.prototype.constructor == Person) // true
复制代码

2、原型链

经过前面咱们对构造函数,对象实例和原型对象三者关系的描述可知,实例都包含了指向原型对象的内部指针。
那么假如如今咱们有两个构造函数AB,咱们让构造函数A的原型对象等于构造函数B的实例,根据前面的推论,这个时候A的原型对象就包含指向B的原型对象的指针,再假如又有一个构造函数C,让A的原型对象等于C的实例,上述关系依旧成立,以此类推便造成了实例与原型的链条,即原型链,它主要做为JS中实现继承的主要方法。post

原型链的基本实现ui

function SuperType() {
    this.property = true;
}
SuperType.prototype.getSuperValue = function() {
    return this.property;
}

# 继承了SuperType
SubType.prototype = new SuperType();
SubType.prototype.getSubValue = function() {
    return this.subproperty;
}

var instance = new SubType();
console.log(instance.SuperValue()); // true
复制代码

在上面的代码中,咱们没有使用SubType默认的原型,而是将SuperType的实例赋给它,重写了SubType的原型对象;这样一来SubType.prototype的内部便具备一个指向SuperType原型的指针,原来存在于SuperType的实例中的全部属性和方法,如今也存在于SubType.prototype中了。
instance同理,还要注意的是因为SubType的原型指向了SuperType的原型,而SuperType的原型的constructor属性指向的是SuperType构造函数,那么instance.constructor也就指向了SuperType
this

以下图所示蓝色的线就表明了原型链spa

原型搜索机制

当访问一个实例属性或方法时,在经过原型链实现继承的状况下,首先会在实例中搜索该属性,在没有找到属性或方法时,便会沿着原型链继续往上搜索,直到原型链末端才会停下来。
这里还有一个重要的点,事实上全部引用类型默认都继承了Object,而这个继承也是经过原型链实现的,也就是说,全部函数的默认原型都是Object的实例,这也是全部自定义类型都会继承toString()valueOf()等默认方法的根本缘由。prototype

Object.prototype的原型
3d

既然全部类型默认都继承了Object,那么Object.prototype又指向哪里呢,答案是null,咱们能够经过下面的代码打印试试看:

console.log(Object.prototype.__proto__ === null) // true
复制代码

null即没有值,也就是说属性或方法的查找到Object.prototype就结束了。

这个时候,咱们就能够看到完整的原型链关系图以下:

结尾

系列文章:

相关文章
相关标签/搜索