www.qjdy.com-奇迹赌场 > www.qjdy.com官网 > Extends的结果与寄生组合继承基本一致

原标题:Extends的结果与寄生组合继承基本一致

浏览次数:150 时间:2019-11-03

黄金时代篇小说了解JS世袭——原型链/构造函数/组合/原型式/寄生式/寄生组合/Class extends

2018/08/02 · JavaScript · 继承

原著出处: 这是你的玩具车吗   

说实在话,从前本身只需求通晓“寄生组合世襲”是最棒的,有个祖传代码模版用就能够。近些日子因为一些作业,多少个星期以来径直时刻不要忘想收拾出来。本文以《JavaScript高端程序设计》上的内容为骨架,补充了ES6 Class的有关内容,从本人认为更易于精晓的角度将持续那件事陈述出来,希望大家能具有收获。

1. 继续分类

先来个总体影像。如图所示,JS中世袭能够依据是还是不是利用object函数(在下文中会提到卡塔 尔(阿拉伯语:قطر‎,将继续分成两部分(Object.create是ES5新扩展的法子,用来标准化这几个函数卡塔 尔(英语:State of Qatar)。

里头,原型链世襲和原型式世袭有一致的利害,构造函数世袭与寄生式世襲也互相照管。寄生组合世襲基于Object.create, 同有的时候候优化了咬合世袭,成为了周密的持续情势。ES6 Class Extends的结果与寄生组合继承基本后生可畏致,但是完成方案又略有分裂。

下边马上踏入正题。

图片 1

2. 后续格局

上海体育场合上半区的原型链世襲,构造函数袭承,组合世袭,英特网内容超多,本文不作详细描述,只提议珍视。这里给出了自己认为最轻松了然的后生可畏篇《JS中的继承(上卡塔尔国》。若是对上半区的内容面生,能够先看那篇作品,再回到继续读书;假若已经相比较熟谙,那部分可以便捷略过。另,上半区大气借出了yq前端的黄金时代篇接二连三散文[1]。

2.1 原型式世襲

主旨:将父类的实例作为子类的原型

SubType.prototype = new SuperType() // 全数关乎到原型链世襲的持续格局都要修正子类构造函数的针对,否则子类实例的构造函数会指向SuperType。 SubType.prototype.constructor = SubType;

1
2
3
SubType.prototype = new SuperType()
// 所有涉及到原型链继承的继承方式都要修改子类构造函数的指向,否则子类实例的构造函数会指向SuperType。
SubType.prototype.constructor = SubType;

优点:父类方法能够复用

缺点:

  • 父类的援用属性会被全体子类实例分享
  • 子类创设实例时无法向父类传递参数

2.2 构造函数世袭

主干:将父类构造函数的开始和结果复制给了子类的构造函数。那是有着继续中唯生机勃勃叁个不关乎到prototype的继承。

SuperType.call(SubType);

1
SuperType.call(SubType);

可取:和原型链世襲完全翻转。

  • 父类的引用属性不会被分享
  • 子类构建实例时能够向父类传递参数

劣点:父类的艺术不可能复用,子类实例的不二秘诀每趟都以单独创制的。

2.3 组合世袭

大旨:原型式世襲和构造函数世袭的结缘,兼具了双面包车型地铁长处。

function SuperType() { this.name = 'parent'; this.arr = [1, 2, 3]; } SuperType.prototype.say = function() { console.log('this is parent') } function SubType() { SuperType.call(this) // 第三遍调用SuperType } SubType.prototype = new SuperType() // 首回调用SuperType

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function SuperType() {
    this.name = 'parent';
    this.arr = [1, 2, 3];
}
 
SuperType.prototype.say = function() {
    console.log('this is parent')
}
 
function SubType() {
    SuperType.call(this) // 第二次调用SuperType
}
 
SubType.prototype = new SuperType() // 第一次调用SuperType

优点:

  • 父类的办法能够被复用
  • 父类的引用属性不会被分享
  • 子类创设实例时能够向父类传递参数

缺点:

调用了五遍父类的构造函数,第三回给子类的原型增加了父类的name, arr属性,第一遍又给子类的构造函数加多了父类的name, arr属性,进而覆盖了子类原型中的同名参数。这种被隐蔽的场合招致了质量上的浪费。

2.4 原型式世襲

主导:原型式世襲的object方法本质上是对参数对象的几个浅复制。

亮点:父类方法能够复用

缺点:

  • 父类的引用属性会被抱有子类实例共享
  • 子类营造实例时无法向父类传递参数

function object(o){ function F(){} F.prototype = o; return new F(); } var person = { name: "Nicholas", friends: ["Shelby", "Court", "Van"] }; var anotherPerson = object(person); anotherPerson.name = "Greg"; anotherPerson.friends.push("Rob"); var yetAnotherPerson = object(person); yetAnotherPerson.name = "Linda"; yetAnotherPerson.friends.push("Barbie"); alert(person.friends); //"Shelby,Court,Van,Rob,Barbie"

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
function object(o){
  function F(){}
  F.prototype = o;
  return new F();
}
 
var person = {
    name: "Nicholas",
    friends: ["Shelby", "Court", "Van"]
};
 
var anotherPerson = object(person);
anotherPerson.name = "Greg";
anotherPerson.friends.push("Rob");
 
var yetAnotherPerson = object(person);
yetAnotherPerson.name = "Linda";
yetAnotherPerson.friends.push("Barbie");
alert(person.friends);   //"Shelby,Court,Van,Rob,Barbie"
 

ECMAScript 5 通过新添Object.create()方法则范化了原型式世襲。那一个办法接受多个参数:叁个用作新对象原型的对象和(可选的)一个为新对象定义额外属性的指标。在传唱一个参数的境况下, Object.create()与 object()方法的行为等同。——《JAVASCript高等编制程序》

所以上文中代码能够转移为

var yetAnotherPerson = object(person); => var yetAnotherPerson = Object.create(person);

1
var yetAnotherPerson = object(person); => var yetAnotherPerson = Object.create(person);

2.5 寄生式世袭

中央:使用原型式世襲拿到三个指标对象的浅复制,然后巩固那几个浅复制的本领。

利弊:仅提供生龙活虎种思路,没什么可取

function createAnother(original){ var clone=object(original); //通过调用函数创立四个新对象 clone.sayHi = function(){ //以某种形式来进步这么些指标 alert("hi"); }; return clone; //再次来到这几个指标} var person = { name: "Nicolas", friends: ["Shelby", "Court", "Van"] }; var anotherPerson = createAnother(person); anotherPerson.sayHi(); //"hi"

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function createAnother(original){
    var clone=object(original);    //通过调用函数创建一个新对象
    clone.sayHi = function(){      //以某种方式来增强这个对象
        alert("hi");
    };
    return clone;                  //返回这个对象
}
 
var person = {
    name: "Nicholas",
    friends: ["Shelby", "Court", "Van"]
};
 
var anotherPerson = createAnother(person);
anotherPerson.sayHi(); //"hi"

2.6 寄生组合世袭

刚刚提起组合世襲有多少个会五回调用父类的构造函数形成浪费的根基差,寄生组合世袭就足以化解那个主题材料。

function inheritPrototype(subType, superType){ var prototype = object(superType.prototype); // 创设了父类原型的浅复制 prototype.constructor = subType; // 改良原型的构造函数 subType.prototype = prototype; // 将子类的原型替换为那么些原型 } function SuperType(name){ this.name = name; this.colors = ["red", "blue", "green"]; } SuperType.prototype.sayName = function(){ alert(this.name); }; function SubType(name, age){ SuperType.call(this, name); this.age = age; } // 核心:因为是对父类原型的复制,所以不带有父类的构造函数,也就不会调用四遍父类的构造函数产生浪费 inheritPrototype(SubType, SuperType); SubType.prototype.sayAge = function(){ alert(this.age); }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
function inheritPrototype(subType, superType){
    var prototype = object(superType.prototype); // 创建了父类原型的浅复制
    prototype.constructor = subType;             // 修正原型的构造函数
    subType.prototype = prototype;               // 将子类的原型替换为这个原型
}
 
function SuperType(name){
    this.name = name;
    this.colors = ["red", "blue", "green"];
}
 
SuperType.prototype.sayName = function(){
    alert(this.name);
};
 
function SubType(name, age){
    SuperType.call(this, name);
    this.age = age;
}
// 核心:因为是对父类原型的复制,所以不包含父类的构造函数,也就不会调用两次父类的构造函数造成浪费
inheritPrototype(SubType, SuperType);
SubType.prototype.sayAge = function(){
    alert(this.age);
}

利弊:那是意气风发种完美的持续格局。

2.7 ES6 Class extends

主导: ES6世襲的结果和寄生组合继承相仿,本质上,ES6一连是风姿洒脱种语法糖。不过,寄生组合世袭是先成立子类实例this对象,然后再对其增进;而ES6先将父类实例对象的习性和措施,加到this上边(所以必得先调用super方法卡塔 尔(英语:State of Qatar),然后再用子类的构造函数修正this。

class A {} class B extends A { constructor() { super(); } }

1
2
3
4
5
6
7
class A {}
 
class B extends A {
  constructor() {
    super();
  }
}

ES6得以完成三番五次的切实原理:

class A { } class B { } Object.setPrototypeOf = function (obj, proto) { obj.__proto__ = proto; return obj; } // B 的实例世襲 A 的实例 Object.setPrototypeOf(B.prototype, A.prototype); // B 世襲 A 的静态属性 Object.setPrototypeOf(B, A);

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class A {
}
 
class B {
}
 
Object.setPrototypeOf = function (obj, proto) {
  obj.__proto__ = proto;
  return obj;
}
 
// B 的实例继承 A 的实例
Object.setPrototypeOf(B.prototype, A.prototype);
 
// B 继承 A 的静态属性
Object.setPrototypeOf(B, A);
 

ES6接续与ES5接续的异同:

相像点:本质上ES6持续是ES5持续的语法糖

不同点:

  • ES6三番三回中子类的构造函数的原型链指向父类的构造函数,ES5中利用的是构造函数复制,未有原型链指向。
  • ES6子类实例的创设,基于父类实例,ES5中不是。

3. 总结

  • ES6 Class extends是ES5一而再的语法糖
  • JS的继续除了构造函数世袭之外都依照原型链创设的
  • 能够用寄生组合继承完成ES6 Class extends,可是仍然会有细微的歧异

参照随笔:

[1]《js世袭、构造函数继承、原型链世襲、组合世襲、组合世襲优化、寄生组合世襲》

[2]《JavaScript高端编制程序》

1 赞 收藏 评论

图片 2

本文由www.qjdy.com-奇迹赌场发布于www.qjdy.com官网,转载请注明出处:Extends的结果与寄生组合继承基本一致

关键词: RT电子游戏 JavaScript

上一篇:为了方便分析页面的加载过程

下一篇:没有了