概念
- 当声明函数(一般只有构造函数我们会关注原型),那么在浏览器内存中会创建一个对象
- 即每个函数都会有一个属性
prototype
指向了这个对象,这个对象就是 原型对象(简称原型) - 原型对象的构造器 constructor 指向了构造函数本身;
- 每一个函数 / class 都有显式原型
prototype
; - 所有实例都有隐式原型
__proto__
~ 指向其构造函数的prototype
;
function Person() {
// 构造函数
}
Person.prototype.sayHello = function () {
console.log('hello')
}
以上代码如图所示: Person.prototype.constructor === Person
- 我们可以用
new
去实例一个对象,实例并没有prototype
属性,通过__proto__
访问到构造函数
Person
的原型对象 - 这里的
__proto__
称作隐式原型,而prototype
称作为显式原型,__proto__
一般用[[Prototype]]
表示
function Person() {
// 构造函数
}
const p = new Person()
以上代码如图所示:
~
原型链
- 使用
extends
来继承父类
class Person {}
Person.prototype.sayHello = function () {
console.log('hello')
}
class Student extends Person {}
const s = new Student()
- 子类(Student)的原型对象会创建一个隐式原型
__proto__
指向父类的原型对象
- Array、String、Boolean …等顶层原型都是
Object
- 而 Object 本身的原型对象的隐式原型
__proto__
指向 null
~
instanceof
本质是实例的隐式原型 __proto__
往原型链上寻找是否有能匹配的显式原型
class Student {
constructor() {}
}
class MiddleStudent extends Student {
constructor() {
super()
}
}
const m = new MiddleStudent()
console.log(m instanceof MiddleStudent) // true
console.log(m instanceof Student) // true
console.log(m instanceof Object) // true
原型设计模式
- JavaScript 中的原型和标准的原型设计模式有差异,并不常用
class CloneDemo {
name = 'clone demo'
clone(): CloneDemo {
return new CloneDemo()
}
}
- Object.create: 但 Object.create 和原型设计模式类似、指定隐式原型
const obj = Object.create({})
console.log(obj.__proto__) // 隐式原型为空
const proto = {
sayHi() {
console.log('hi')
}
}
const obj = Object.create(proto) // obj 的隐式原型指向了 proto
console.log(obj)
其他继承方式
- getPrototypeof:获取实例的原型
- setPrototypeOf:前者继承后者的原型
const animal = {
hasEyes: true
}
const dog = {
type: '金毛'
}
Object.setPrototypeOf(dog, animal)
console.log(dog.hasEyes) // dog 的原型上有 hasEyes 属性