Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
webVueBlog opened this issue Sep 16, 2022 · 0 comments
Open

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

webVueBlog opened this issue Sep 16, 2022 · 0 comments

Comments

@webVueBlog
Copy link
Member

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

原型式继承的基本思想

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

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;
}

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

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant