关灯
开启左侧

extends

[复制链接]
紫米 发表于 2019-4-23 16:36:49 | 显示全部楼层 |阅读模式 打印 上一主题 下一主题
 
ES6中有关class的继承方式,引入了extends关键字。但其本质仍然是构造函数+原型链的组合式继承。
例1:
  1. class A {
  2.     constructor(name, age) {
  3.         this.name = name;
  4.         this.age = age;
  5.     }
  6.     getName() {
  7.         return this.name;
  8.     }
  9. }

  10. class B extends A {
  11.     constructor(name, age) {
  12.         super(name, age);
  13.         this.job = "IT";
  14.     }
  15.     getJob() {
  16.         return this.job;
  17.     }
  18.     getNameAndJob() {
  19.         return super.getName() + this.job;
  20.     }
  21. }

  22. var b = new B("Tom", 20);
  23. console.log(b.name);
  24. console.log(b.age);
  25. console.log(b.getName());
  26. console.log(b.getJob());
  27. console.log(b.getNameAndJob());
  28. //输出:Tom,20,Tom,IT,TomIT
复制代码

1.extends关键字

上面代码定义了一个B类(class),该类通过extends关键字,继承了A类的所有属性和方法。A类中的所有方法默认是添加到B的原型上,所以extends继承的实质仍然是原型链。

测试代码:

  1. console.log("constructor" in b);
  2. console.log("getName" in b);
  3. console.log(b.hasOwnProperty("getName"));
  4. console.log(b.hasOwnProperty("constructor"));
  5. //输出:true,true,false,false
复制代码
2.super关键字
super这个关键字,既可以当作函数使用,也可以当作对象使用。当作函数使用时,super代表父类的构造函数,并在子类中执行Parent.apply(this),从而将父类实例对象的属性和方法,添加到子类的this上面。以下三点需要特别注意:

1、子类必须在constructor方法中调用super方法,如果子类没有定义constructor方法,constructor方法以及其内部的super方法会被默认添加。

测试代码:

  1. class A {
  2.     constructor(name, age) {
  3.         this.name = name;
  4.         this.age = age;
  5.     }
  6.     getName() {
  7.         return this.name;
  8.     }
  9. }

  10. class B extends A {}

  11. var b = new B("Tom", 20);

  12. console.log(b.name);
  13. console.log(b.age);
  14. console.log(b.getName());
  15. console.log(b.hasOwnProperty("name"));
  16. //输出:Tom,20,Tom,true
  17. 2、在子类的constructor方法中,只有调用super之后,才可以使用this关键字,否则会报错。

  18. 测试代码:

  19. class A {
  20.     constructor(name, age) {
  21.         this.name = name;
  22.         this.age = age;
  23.     }
  24. }

  25. class B extends A {
  26.     constructor(name, age) {
  27.         this.job = "IT";
  28.         super(name, age);
  29.     }
  30. }

  31. var b = new B("Tom", 20)
  32. //输出:报错
复制代码
super()只能用在子类的constructor方法之中,用在其他地方就会报错。
测试代码:
  1. class A {
  2.     constructor(name, age) {
  3.         this.name = name;
  4.         this.age = age;
  5.     }
  6. }

  7. class B extends A {
  8.     toStr(name, age) {
  9.         super(name, age)
  10.     }
  11. }

  12. var b = new B("Tom", 20)
  13. //输出:报错
复制代码
super作为对象时,在子类中指向父类的原型对象。
即super=Parent.prototype。

测试代码:

  1. class A {
  2.     constructor(name, age) {
  3.         this.name = name;
  4.         this.age = age;
  5.     }
  6.     getName() {
  7.         console.log(this.name);
  8.     }
  9. }
  10. A.prototype.n = 2;

  11. class B extends A {
  12.     constructor(name, age) {
  13.         super(name, age);
  14.     }
  15.     toStr() {
  16.         return super.n;
  17.     }
  18.     activeGetName() {
  19.         super.getName();
  20.     }
  21. }

  22. var b = new B("Tom", 20);
  23. console.log(b.toStr());
  24. console.log(b.activeGetName());
  25. //输出:2,Tom
复制代码
3.静态方法的继承

在一个方法前加上关键字static,就表示该方法不会被实例继承,但是父类的静态方法,会被子类继承

例2
  1. class A {
  2.     static say() {
  3.         console.log("hello");
  4.     }
  5. }

  6. class B extends A {}

  7. console.log(B.say());
  8. //输出:hello
复制代码


也可以使用super在子类的静态方法中调用父类的静态方法。super在静态方法中指向父类本身,而不是父类的原型对象。

例3:

  1. class A {
  2.     static say() {
  3.         console.log("hello");
  4.     }
  5. }

  6. class B extends A {
  7.     static toStr() {
  8.         super.say();
  9.     }
  10. }
  11. var b = new B();
  12. console.log(B.toStr());
  13. //输出:hello
复制代码
继承表达式的类
类不但可以继承自其他类,也可以继承表达式。只要表达式可以被解析为一个函数并且通过new关键字可以创建新的实例对象即可。


例4:
继承传统形式的构造函数

  1. let Obj = function(name) {
  2.     this.name = name;
  3. }
  4. Obj.prototype.getName = function() {
  5.     console.log(this.name);
  6. }

  7. class Person extends Obj {
  8.     constructor(name, age) {
  9.         super(name);
  10.         this.age = age;
  11.     }
  12. }

  13. const p = new Person("Tom", 19);

  14. console.log(p.name); //输出:Tom
  15. console.log(p.age); //输出:19
  16. p.getName(); //输出:Tom
复制代码
例子5:
继承函数返回结果

  1. let fn = function() {
  2.     return class Person {
  3.         constructor(name) {
  4.             return {
  5.                 name
  6.             }
  7.         }
  8.     }
  9. }

  10. class SomeOne extends fn() {
  11.     constructor(name) {
  12.         super(name);
  13.     }
  14. }

  15. let p = new SomeOne("Tom");
  16. console.log(p.name); //输出:Tom
复制代码
4.New.target
我们知道,函数内部有一个new.target对象用于判断函数是否通过new关键字调用。类构造函数也可以通过new.target来确定类的调用形式。
  1. class Obj {
  2.     //new Obj()时,new.target的值为 Obj
  3.     constructor() {
  4.         if (new.target === Obj) {
  5.             console.log("不可以直接调用基类!");
  6.         }
  7.     }
  8.     fn() {
  9.         console.log(this.name);
  10.     }
  11. }

  12. class Person extends Obj {
  13.     //new Person("Tom")时,new.target的值为 Person
  14.     constructor(name) {
  15.         super();
  16.         this.name = name;
  17.     }
  18. }

  19. let p1 = new Person("Tom");
  20. p1.fn(); //输出:Tom
  21. let p2 = new Obj(); //输出:不可以直接调用基类!
复制代码
因为类必须通过new关键字调用,所以在类的构造函数中new.target的值永远不会是undefined。
 
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

排行榜
关闭

站长推荐上一条 /1 下一条

官方微信

全国服务热线:

400-0708-360

公司地址:国家西部信息安全产业基地(成都市高新区云华路333号)

邮编:610000    Email:2908503813@qq.com

Copyright   ©2015-2016  EOIT论坛Powered by©Discuz!    ( 蜀ICP备11000634号-7 )