ChickenDreamFactory/fe-chicken

75.实现原型式继承-寄生式继承-寄生组合式继承

Opened this issue · 0 comments

实现原型式继承-寄生式继承-寄生组合式继承

原型式继承的基本**

原型式继承是,借助原型可以基于已有的对象创建新对象,同时还不比自己创建自定义类型

1.题目:请写出原型式继承的示例,举例原型式继承的优缺点,使用原型式继承的场景

__

寄生式继承的基本**

寄生式继承是,创建一个仅用于封装继承过程的函数,该函数内部以某种方式增强对象,然后再像真的是它做了所有工作一样的返回对象。

2.题目:请写出寄生式继承的示例,举例寄生式继承的优缺点,使用寄生式继承的场景

__

寄生组合式继承的基本**

前面的题目说过,组合继承其实是js里面用到的最广泛的继承模式,但是组合继承也有自己的缺点就是,无论什么情况下都会调用两次的超类型构造函数,一次是在创建子类型的原型的时候,一次是在子类型构造函数的内部。寄生组合式继承的高效在于它只调用一次超类型构造函数,避免了创造不必要的多的函数和属性在子类型上面。是引用类型最理想的继承范式。

3.题目:请写出寄生组合式继承的示例,举例寄生组合式继承的优缺点,使用寄生组合式继承的场景

// 原型式继承
function createObj (o) {
 function F() {};
 F.prototype = o;
 return new F();
}

// 寄生式继承
function createObj (o) {
 var clone = Object.create(o);
 clone.sayName = function() {
  console.log('hi');
 }
 return clone;
}

// 寄生组合式继承
function Parent(name) {
  this.name = name;
  this.colors = ['red', 'blue', 'green'];
}

Parent.prototype.getName = function() {
  console.log(this.name)
}

function Child (name, age) {
  Parent.call(this, name);
  this.age = age;
}

// 关键  方法一
// var F = function () {};
// F.prototype = Parent.prototype;
// Child.prototype = new F();

// 关键 方法二
function object(o) {
  function F() {}
  F.prototype = o;
  return new F();
}

function inheritPrototype(child, parent) {
  var prototype = object(parent.prototype);
  prototype.constructor = child;
  child.prototype = prototype;
}


inheritPrototype(Child, Parent);

var child1 = new Child('dada', '18')

console.log(child1)

原型式继承

function object(o) {
 function F() {}
 F.prototype = o;
 return new F();
}

在函数内部,先创建 临时性的构造函数,然后将传入的对象作为这个 构造函数的原型,最后返回这个临时构造函数的一个实例。从本质上,该函数对传入的对象执行了一次 浅拷贝。

ECMAScript 5 通过增加 Object.create()方法

这个方法接收两个参数:作为新对象原型的对象,以及给新对象定义额外属性的对象(第二个可选)

let person = {
 name: "Nicholas",
 friends: ["Shelby", "Court", "Van"]
};
let anotherPerson = Object.create(person, {
 name: {
 value: "Greg"
 }
});
console.log(anotherPerson.name); // "Greg"

场景:

原型式继承非常适合不需要单独创建构造函数,但仍然需要在对象间共享信息的场合

缺点:

属性中包含的引用值始终会在相关对象间共享,跟使用原型模式是一样的。(引用类型值的属性始终都会共享相应的值,多个实例对象对引用类型的操作会被篡改。)

原型式继承是借助原型基于已有的对象创建新对象,同时还不必因此创建自定义类型。

function Person(friendship) {
  function Creator() {}
  Creator.prototype = friendship;
  return new Creator();
}

寄生式继承

寄生式继承背后的思路类似于寄生构造函数和工厂模式:创建一个实现继承的函数,以某种方式增强对象,然后返回这个对象。

function createAnother(original){
 let clone = object(original); // 通过调用函数创建一个新对象
 clone.sayHi = function() { // 以某种方式增强这个对象
 console.log("hi");
 };
 return clone; // 返回这个对象
} 

场景:

寄生式继承同样适合主要关注对象,而不在乎类型和构造函数的场景。(在主要考虑对象而 不是自定义类型和构造函数的情况下,寄生式继承也是一种有用的模式。)

寄生式继承(Parasitic Inheritance):创建一个仅用于封装继承过程的函数,在函数内部以某种方式增强对象

function creator(origin) {
  // 以 origin 为原型对象创建一个新对象
  let clone = Object.create(origin);

  // 以某种方式来增强这个对象
  clone.sayHi = function () {
    console.log('Hello world!');
  };

  // 返回这个对象
  return clone;
}

⚠️ 注意: 使用寄生式继承来为对象添加函数,会由于不能做到函数复用而降低效率;这一点与借用构造函数模式类似。

寄生组合式继承

寄生组合式继承,即通过借用构造函数来继承属性,通过原型链的混成形式来继承方法。
(寄生式组合继承通过盗用构造函数继承属性,但使用混合式原型链继承方法。)

组合继承的例子:

function SubType(name, age){
 SuperType.call(this, name); // 第二次调用 SuperType()
 this.age = age;
}
SubType.prototype = new SuperType(); // 第一次调用 SuperType()
function inheritPrototype(subType, superType) {
 let prototype = object(superType.prototype); // 创建对象
 prototype.constructor = subType; // 增强对象
 subType.prototype = prototype; // 赋值对象
}

不必为了指定子类型的原型而调用超类型的构造函数,我们所需要的无非就是超类型原型的一个副本而已。 本质上,就是使用寄生式继承来继承超类型的原型,然后再将结果指定给子类型的原型。

function inherit(child, parent) {
  // 创建对象
  let prototype = Object.create(parent.prototype);

  // 增强对象
  prototype.constructor = child;

  // 指定对象
  child.prototype = prototype;
}

这个函数接收两个参数:子类型构造函数 和 超类型构造函数。

寄生式组合继承可以算是引用类型继承的最佳模式。