原型和原型链
原型与原型链的概念
原型:
我们创建的每个函数都有一个 prototype(原型) 属性,这个属性指向一个对象,而这个原型对象包含它的实例对象所共享的属性和方法。
图解:
-
每一个构造函数都拥有一个 prototype 属性,这个属性指向一个对象,也就是原型对象
-
原型对象默认拥有一个 constructor 属性,指向指向它的那个构造函数
-
每个对象都拥有一个隐藏的属性 proto,指向它的原型对象
原型链:
每个实例对象( object )都有一个私有属性(称之为__proto__
)指向它的构造函数的原型对象(prototype)。该原型对象自身也是一个对象,也有它自己的原型对象(__proto__
) ,层层向上直到一个对象的原型对象为null。根据定义,null没有原型,并作为这个原型链中的最后一个环节。
这句话特别重要:
- 每个实例对象都有一个私有属性:
__proto__
,该私有属性 指向实例构造函数的原型对象。
// 父类
class People {
constructor(name) {
this.name = name
}
eat() {
console.log(`${this.name} eat something`)
}
}
// 子类
class Student extends People {
constructor(name, number) {
super(name)
this.number = number
}
sayHi() {
console.log(`姓名 ${this.name} 学号 ${this.number}`)
}
}
// 子类
class Teacher extends People {
constructor(name, major) {
super(name)
this.major = major
}
teach() {
console.log(`${this.name} 教授 ${this.major}`)
}
}
// 实例
const xialuo = new Student('夏洛', 100)
console.log(xialuo.name)
console.log(xialuo.number)
xialuo.sayHi()
xialuo.eat()
// 实例
const wanglaoshi = new Teacher('王老师', '语文')
console.log(wanglaoshi.name)
console.log(wanglaoshi.major)
wanglaoshi.teach()
wanglaoshi.eat()
显示原型和隐示原型
显示原型prototype自己带有方法,比如学生类中自己有的sayHi()方法。
隐示原型__proto__自己没有的方法,但是自己父类有的方法,如学生类的父类People中的eat()方法。
总结:
-
每一个实例对象都有一个私有属性
__proto__
,该私有属性总是指向实例构造函数的原型对象; -
不同的原型对象”节点“通过
__proto__
指向进行串联连接,从而形成一条原型链。 -
原型链的终点为 null 对象,即无中生有。
通过使用 hasOwnProperty
可以确定访问的属性是来自于实例还是原型对象
function Person() {}
Person.prototype = {
name: 'tt'
}
var p = new Person();
p.age = 15;
//hasOwnProperty是不是自己的属性
p.hasOwnProperty('age') // true
p.hasOwnProperty('name') // false