1. <!DOCTYPE html>
    2. <html lang="en">
    3. <head>
    4. <meta charset="UTF-8">
    5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
    6. <title>组合继承</title>
    7. </head>
    8. <body>
    9. </body>
    10. </html>
    11. <script>
    12. /**
    13. * 组合继承:
    14. * 原型继承 + 构造函数继承
    15. * 避免了原型 && 构造函数 继承的缺点,融合他们的优点
    16. * 优点:
    17. * 可以使用原型上的方法和属性;
    18. * 实现给父级构造函数传参
    19. * 缺点:
    20. * 创建实例的原型上会存在两份属性
    21. * 父类构造函数调用一次,子类原型实现时候又会调用父类构造函数一次。因此会调用两次
    22. */
    23. function Person(name) {
    24. this.name = name || 'not name';
    25. this.books = ['html', 'css'];
    26. Person.prototype.getName = function () {
    27. console.log(`父级类的方法得到的name${this.name}`);
    28. }
    29. }
    30. function Adult(name, time) {
    31. this.time = time
    32. // 构造函数继承父类 && 传参name属性
    33. Person.call(this, name);
    34. Adult.prototype.getTime = function () {
    35. console.log(this.time);
    36. }
    37. }
    38. Adult.prototype = new Person();
    39. // 是否设置下面这一行,具体请看65行
    40. Adult.prototype.constructor = Adult;
    41. // 子类属性修改后不会影响其他实例
    42. // 子类的参数可以传递给父类
    43. let ming = new Adult('小明', 0000);
    44. let hong = new Adult('小红', 2020);
    45. ming.books.push('vue') // books: (3) ["html", "css", "vue"]
    46. hong.books.push('react'); // books: (3) ["html", "css", "react"]
    47. // 两个构造函数上面都会增加 books 和name属性 可以在增加属性测试
    48. console.log(ming);
    49. console.log(hong);
    50. ming.getTime() // 0
    51. hong.getTime() // 2020
    52. ming.getName() // 父级类的方法得到的name:小明
    53. hong.getName() // 父级类的方法得到的name:小红
    54. // 讨论是否设置 constructor 问题 https://www.zhihu.com/question/19951896/answer/13457869
    55. // 下面假设如果没有设置 Adult.prototype.constructor = Adult
    56. console.log(Adult.prototype.constructor); // ƒ Person(name) {}
    57. console.log(Person.prototype.constructor); // ƒ Person(name) {}
    58. // 设置上之后 Adult.prototype.constructor = Adult
    59. console.log(Adult.prototype.constructor); // ƒ Adult(name, time) {}
    60. console.log(Person.prototype.constructor); // ƒ Person(name) {}
    61. </script>