8. 原型和继承

  1. 原型和原型链分别是什么?描述 JavaScript 内置的原型链。
    a . 原型 :

    JavaScript中我们每创建一个函数都有prototype(原型)属性,指向原型对象,原型对象的用途是包含可以特定类型的所有实例共享的属性和方法。


b. 原型链

  1. 描述实例,构造函数,原型的联系。
    • 每一个构造函数都拥有一个prototype属性,这个属性指向一个对象,也就是原型对象
    • 原型对象默认拥有一个constructor属性,指向它的那莪构造函数
    • 每个对象都拥有一个隐藏属性__prototype__,指向它的原型对象 ```javascript function Person() {}

let person = new Person();

person.proto === Person.prototype //true

Person.prototype.constructor === Person //true

  1. **原型特点 : **
  2. - 实例可以共享原型上面的属性和方法
  3. - 实例调用属性会先从自身找,若自身没有才会去原型上面找
  4. 3. 罗列各种实现继承的方式,并用代码展示。
  5. - 原型链继承
  6. ```javascript
  7. function Parent() {
  8. this.name = "Parent";
  9. }
  10. Parent.prototype.sayHi = function() {
  11. console.log('Hi !!!');
  12. }
  13. function Child() {
  14. this.name = 'Child';
  15. }
  16. Child.prototype = new Parent();
  17. let c1 = new Child();
  18. console.log(c1);
  • 寄生式继承
    寄生式继承就是用一个函数包装一个对象,然后返回这个函数的调用,这个函数就变成了个可以随意增添属性的实例或对象。 ```javascript function object(obj) { let clone = Object(obj); clone.sayHi = function() {
    1. console.log("Hi !!!");
    } return clone; }

let sub = { name:’sub’ } let sup = object(sub); console.log(sup);

  1. - 盗用构造函数<br />在字类构造函数中调用父类构造函数。我们可以用`.call()``.apply()`将父类构造函数引入子类函数。
  2. ```javascript
  3. function SuperType() {
  4. this.names = ["jackson", "bear"];
  5. }
  6. function SubType() {
  7. // 继承 SuperType
  8. SuperType.call(this);
  9. }
  10. let instance1 = new SubType();
  11. instance1.names.push("daxiong");
  12. console.log(instance1.names); // ["jackson", "bear", "daxiong"]
  13. let instance2 = new SubType();
  14. console.log(instance2.names); // ["jackson", "bear"]
  • 组合继承

    组合继承(经典继承)综合了原型链和盗用构造函数,将两者的优点集中起来,基本的思路就是使用原型链继承原型上的属性和方法,而通过盗用构造函数继承实例属性,这样既可以吧方法定义在原型上以实现重用,又可以让每个实例都有自己的属性,

  1. function SuperType(name) {
  2. this.name = name;
  3. this.colors = ['red','blue','grenn'];
  4. }
  5. SuperType.prototype.sayName = function() {
  6. console.log(this.name);
  7. }
  8. function SubType(name,age) {
  9. SuperType.call(this,name);
  10. this.age = age;
  11. }
  12. SubType.prototype = new SuperType();
  13. SubType.prototype.constructor = SubType;
  14. SubType.prototype.sayAge = function(){
  15. console.log(this.age);
  16. }
  17. console.log(new SubType());
  • 寄生式组合继承

寄生式组合继承通过调用构造函数继承属性,但是用混合式原型链的集成方法,但基本思路是不通过调用父类构造函数给子类原型赋值,而是取得父类原型的一个副本,说到底就是使用寄生式来继承父类原型,然后将返回的新对象赋值给子类对象

  1. function inheritPrototype(SubType,SuperType) {
  2. let prototype = Object(SuperType.prototype) //创建对象
  3. prototype.constructor = SubType; //增强对象
  4. SubType.prototype = prototype; //赋值对象
  5. }
  6. /*
  7. 这个函数接收两个参数(子类构造函数,父类构造函数),在这个函数内部,
  8. 第一步是父类原型的一个副本,然后,给返回的prototype对象设置constrcutor
  9. 属性,解决了由于重写类型导致的默认constructor丢失问题,最后将创建
  10. 的对象赋值给子类型的原型
  11. */
  12. function SuperType(name) {
  13. this.name = name;
  14. this.colors = ['red','green'];
  15. }
  16. SuperType.prototype.sayName = function() {
  17. console.log(this.name);
  18. }
  19. function SubType(name,age) {
  20. SuperType.call(this,name);
  21. this.age = age
  22. }
  23. inheritPrototype(SubType,SuperType);
  24. console.log(new SubType('wbt',19));