<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>组合继承</title></head><body></body></html><script> /** * 组合继承: * 原型继承 + 构造函数继承 * 避免了原型 && 构造函数 继承的缺点,融合他们的优点 * 优点: * 可以使用原型上的方法和属性; * 实现给父级构造函数传参 * 缺点: * 创建实例的原型上会存在两份属性 * 父类构造函数调用一次,子类原型实现时候又会调用父类构造函数一次。因此会调用两次 */ function Person(name) { this.name = name || 'not name'; this.books = ['html', 'css']; Person.prototype.getName = function () { console.log(`父级类的方法得到的name:${this.name}`); } } function Adult(name, time) { this.time = time // 构造函数继承父类 && 传参name属性 Person.call(this, name); Adult.prototype.getTime = function () { console.log(this.time); } } Adult.prototype = new Person(); // 是否设置下面这一行,具体请看65行 Adult.prototype.constructor = Adult; // 子类属性修改后不会影响其他实例 // 子类的参数可以传递给父类 let ming = new Adult('小明', 0000); let hong = new Adult('小红', 2020); ming.books.push('vue') // books: (3) ["html", "css", "vue"] hong.books.push('react'); // books: (3) ["html", "css", "react"] // 两个构造函数上面都会增加 books 和name属性 可以在增加属性测试 console.log(ming); console.log(hong); ming.getTime() // 0 hong.getTime() // 2020 ming.getName() // 父级类的方法得到的name:小明 hong.getName() // 父级类的方法得到的name:小红 // 讨论是否设置 constructor 问题 https://www.zhihu.com/question/19951896/answer/13457869 // 下面假设如果没有设置 Adult.prototype.constructor = Adult console.log(Adult.prototype.constructor); // ƒ Person(name) {} console.log(Person.prototype.constructor); // ƒ Person(name) {} // 设置上之后 Adult.prototype.constructor = Adult console.log(Adult.prototype.constructor); // ƒ Adult(name, time) {} console.log(Person.prototype.constructor); // ƒ Person(name) {}</script>