添加class值_Class类的继承

嗯,class 的基本用法已经写过了,如果对 class 类的基本语法不太了解的话,可以参考一下ES6 Class 的基本语法

简介

Class 可以通过 extends 关键字实现继承,这比 ES5 的通过修改原型链实现继承,要清晰和方便很多。

18fb7441cc6f25628fae7776cc53fa1b.png

上面代码定义了一个 ColorPoint 类,该类通过 extends关键字,继承了 Point 类的所有属性和方法。

基础用法

1448ba54af758344b242e3814bc65091.png

上面代码中,子类的 constructor 方法中出现了 super 关键字,它在这里表示父类的构造函数,用来新建父类的 this 对象。

子类必须在 constructor 方法中调用 super 方法,否则新建实例时会报错。这是因为子类自己的 this 对象,必须先通过父类的构造函数完成塑造,得到与父类同样的实例属性和方法,然后再对其进行加工,加上子类自己的实例属性和方法。如果不调用 super 方法,子类就得不到 this 对象。

eg:

7c56babd7ba5c4c961c2b78ee3701bb1.png

上面代码中,Child 继承了父类Father,但是它的构造函数没有调用 super 方法,导致新建实例时报错。

对于子类和父类方法重复的情况,在子类中调用父类与子类的同名方法同样通过super 关键字:

子类和父类方法不同名时,直接this调用:

27773d5d0cd640770c1cbb493adcd17c.png

子类与父类方法名重叠时:

b550556258ce844f911a8c58f18945c3.png

其实是它调用自身,形成无限递归(因为子类和父类重名时,使用this优先调用子类自身的方法)! 这种情况明显是不行的,所以要解决这种情况,通过super 关键字区分即可,调用子类方法用this , 调用父类方法用super 。

0f36ac5c4c541bbaefefa1dda717e926.png

虽然说如果父类的方法子类没有的话,可以通过this.方法名调用,但是我个人的话还是建议调用子类自身的方法通过this.方法名,调用父类方法通过super.方法名。这样可以便于区分,同时也不用但是父类和子类方法名重名问题。

继承同ES5区别

ES5 的继承,实质是先创造子类的实例对象this,然后再将父类的方法添加到this上面(Parent.apply(this))。ES6 的继承机制完全不同,实质是先将父类实例对象的属性和方法,加到this上面(所以必须先调用super方法),然后再用子类的构造函数修改this

当子类没有定义constructor时

如果子类没有定义constructor方法,这个方法会被默认添加,代码如下。也就是说,不管有没有显式定义,任何一个子类都有constructor方法。

2d67e96da497e34593b4426e8a6283b8.png

等同于:

d9811ab9ecc41e798c28faa280cdb89e.png

子类的constructor只有先调用super,才能使用this关键字

子类的constructor方法没有调用super之前,就使用this关键字,结果报错,而放在super方法之后就是正确的。

578b66baecaa2d5fb38094d2c3547c5b.png

正确示范:

0335fffb2ac5ab8fce5fbdb513f07b99.png

super 关键字

super 这个关键字,既可以当作函数使用,也可以当作对象使用。在这两种情况下,它的用法完全不同。

第一种情况,super作为函数调用时,代表父类的构造函数。ES6 要求,子类的构造函数必须执行一次super函数。

de1361927b066c0face553e8f8de3ca0.png

上面代码中,子类B的构造函数之中的super(),代表调用父类的构造函数。这是必须的,否则 JavaScript 引擎会报错。

注意,super虽然代表了父类A的构造函数,但是返回的是子类B的实例,即super内部的this指的是B的实例,因此super()在这里相当于A.prototype.constructor.call(this)。

即类似于es6之前的构造函数中的这种写法:

5db2f34fd130de3e14ac11641e72ab04.png

eg:

cc6c6754761f72c05426d38daf14542f.png

上面代码中,new.target指向当前正在执行的函数。可以看到,在super()执行时,它指向的是子类Child的构造函数,而不是父类Father的构造函数。也就是说,super()内部的this指向的是Child

作为函数使用时,super()只能用在子类的构造函数之中,用在其他地方就会报错。

33091b3b2d5c1114ef0fa3c7db7d940c.png

上面代码中,console.log(super)当中的super,无法看出是作为函数使用,还是作为对象使用,所以 JavaScript 引擎解析代码的时候就会报错。这时,如果能清晰地表明super的数据类型,就不会报错。

eg:

2d6292dd406c64dcf8ae59ad8647bdec.png

默认情况下, valueOf() 会被每个对象Object继承。每一个内置对象都会覆盖这个方法为了返回一个合理的值,如果对象没有原始值,valueOf() 就会返回对象自身。

类的 prototype 属性和__proto__属性

大多数浏览器的 ES5 实现之中,每一个对象都有__proto__属性,指向对应的构造函数的prototype 属性。Class 作为构造函数的语法糖,同时有 prototype 属性和 __proto__ 属性,因此同时存在两条继承链。

子类的__proto__属性,表示构造函数的继承,总是指向父类。

2d5b2b0ccbecd2dbd0509b51aec61fa8.png

子类prototype属性的__proto__属性,表示方法的继承,总是指向父类的prototype属性。

e2cc795d2b66d1830a9612d717cccf3b.png

实例的 __proto__ 属性

子类实例的__proto__属性的__proto__属性,指向父类实例的__proto__属性。也就是说,子类的原型的原型,是父类的原型。

03a4749ea86ad119d0a87e2bf326a446.png

因此,通过子类实例的__proto__.__proto__属性,可以修改父类实例的行为。

eg:

c45b74e8a93f12a3e909b36f0236b4b0.png

后面还有 原生构造函数的继承 ,Mixin 模式的实现 两节 ,但是我理解不够透彻,写出来容易误导大家,所以希望大家看阮一峰大佬的:http://es6.ruanyifeng.com/#docs/class-extends

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值