我是结合慕课和 JS 高级程序设计这本书去学习继承这部分的内容的。在慕课《JavaScript 深入浅出》那一教程的 OOP(Object Oriented Programming 面向对象程序设计)章节。
原型链
首先我们了解原型链。在 ECMAScript 中描述了原型链的概念,并将原型链作为实现继承的主要方法。
1 | function foo() {} |
这边我们创建一个 foo 构造函数,并创建了一个对象实例 obj,对象 obj 的内部有一内部属性[[prototype]] (跟图中的[[proto]]是同一个东西) ,该属性是一个指针,因为是用 new 命令实例化对象,我们来回顾下 new 命令在使用时进行的操作.
- 创建一个新的对象
- 为这个新建对象进行[[prototype]]连接
- 将 this 值绑定到这个新建对象上
- 如果函数没有返回其他对象就返回这个对象
执行 new 命令操作的第 2 步中,将对象 obj 的[[prototype]]属性,(它是一个指针) 指向到其对应的原型对象 foo.prototype
foo.prototype 这个原型对象其内部也有一个[[prototype]]属性,指向 Object.prototype
我们可以用 isPrototypeOf()方法来确定对象之间是否存在这种关系
1 | console.log(foo.prototype.isPrototypeOf(obj)) // true |
我们用原型对象的 isPrototypeOf( )方法测试了 obj 和 foo.prototype,
对象实例 obj 内部有一个指针指向 foo.prototype 所以返回了 true
因为 foo.prototype 内部有一个指针指向 Object.prototype 所以返回了 true
Object.prototype 指向 null,这条原型链的尽头就是 Object.prototype
所以上图就是一个简单的完整的原型链~ 明确了原型链是什么之后,我们就来了解如何利用原型链实现继承。
实现继承
继承的本质在于重写原型对象,往往通过重写构造函数的原型对象去实现继承
实现继承的方法
利用原型链
1 | //继承了Human 以下两种方式都可以实现继承 |
1 | Object.create(proto, [ propertiesObject ]) //语法 |
Object.create() 方法创建一个拥有指定原型和若干个指定属性的对象。
参数
proto : 一个对象,作为新建对象的原型
propertiesObject : 可选。该参数对象是一组属性与值,
举个例子
1 | function Human() {} |
利用原型链的确可以,但是我的上一篇笔记有说过,原型模式的问题是当构造函数含有引用类型值(如数组)的属性时,修改这种属性的值,所有实例共享属性,所有实例也会发生变化。这显然不是我们想要的