前端学习(六十) JavaScript-class继承(javaScript)
继承
在说继承之前,先看在E5及以前是怎么做继承的,下例是最常用的组合继承
function Co4(name,age){
this.name=name;
this.age=age;
}
Co4.prototype={
constructor:Co4,
sayName:function(){
console.log(this.name)
}
}
function Co4N(name,age){
Co4.call(this,name,age) //将对象指向Co4,如果没有,那么会默认指向Obejct
}
Co4N.prototype=new Co4();
Co4N.prototype.constructor=Co4;
Co4N.prototype.sayAge=function(){
console.log(this.age);
}
let ah=new Co4N("ddd",123)
ah.sayAge()
在ES6中的类里面,用到了关键字extends,先看示例
class da{}
class da1 extends da{}
那么上面ES5中的写法,改成类的写法,如下例
class da{
constructor(name,age){
this.name=name;
this.age=age
}
sayName(){
console.log(this.name);
}
sayAge(){
console.log(this.age);
}
}
class da1 extends da{
constructor(name,age){
super(); //一定要写表面调用父级方法
this.name=name;
this.age=age;
}
sayAge(){
super.sayAge()
}
sayName(){
super.sayName()
}
}
let da2=new da1('aaarac',20);
da2.sayAge() //20
da2.sayName() //aaarac
这边有几个注意点,子类必须在constructor中调用super方法,就跟ES5中Co4.call(this,name,age),指明this是指向的Co4以及Co4N.prototype.constructor=Co4指明构造函数是Co4一样
至于为什么一定要在constructor中定义super()方法,实际上,当我们将子类实例化以后da1虽然是继承(extends)自da,但是并没有将父类的this一起继承过来,而本身又没有this,所以会报错,因此要用super来将父类的this一起拿过来,而且,super()在constructor中一定要置顶写,因为上面也说了,子类本身没有this的,所以如果this.name=name写在super()之前,那么会报一个错误,大致就是找不到this
那么静态方法呢,设置super()之后,会不会继承过来,上一篇没有设置super之前,子类是无法访问父类的static也就是静态方法的,答案是肯定的,如下示例
class Es6dd{
constructor(){}
static sayName(){
console.log("hehesayName");
return "he2he2say2Name";
}
}
class Es6dd1 extends Es6dd{
constructor(name){
super();
this.name=name;
}
sayName(){
console.log(this.name);
console.log(super.sayName());
}
}
let _es6dd=new Es6dd1('hehehe');
_es6dd.sayName();
判断子类是否来源于某个父类
Object.getPrototypeOf()方法,这样就可以判断子类的归属
console.log(Object.getPrototypeOf(Es6dd1) === Es6dd); //true
super
在class中,super是一个非常重要的关键字,作用是继承父类里的属性和方法,super一共有两种用法
- 当方法使用super()
- 当关键字使用,super.xxx
当作方法使用时,也就是super(),必须放在constructor里,否则会报错,例如
class Es6e{
constructor(){}
fuc(){
super(); //报错
}
}
当作关键字使用时,不能直接使用,如下例
class Es6e{
constructor(){
super();
console.log(super); //报错,super后面需要跟上其他关键字方法,以用来调用父级类的属性方法
}
}
然后super可以在其他方法里使用,作用是调用父级元素的属性方法
class Es6dd{
constructor(){}
static sayName(){
return "he2he2say2Name";
}
sayAge(){
return "123";
}
}
class Es6dd1 extends Es6dd{
constructor(name,age){
super();
this.name=name;
this.age=age
}
static sayName(){
console.log(super.sayName());
//console.log(super.sayName === Es6dd.prototype.sayName);
}
sayAge(){
console.log(super.sayAge());
}
}
Es6dd1.sayName()
let _es6dd=new Es6dd1('hehehe');
_es6dd.sayAge();
注意:静态方法只能被静态方法调用,非静态方法只能访问非静态方法,不能是非静态方法访问静态方法
如果进一步对比,会发现super调用是完全对等的,也可以这么说super === 父类.prototype
console.log(super.sayName === Es6dd.prototype.sayName); //true
进一步了解super
class n{
constructor(){
this.age = 18
}
}
class n1 extends n{
constructor(){
super();
console.log(this.age); //18
this.age=6;
console.log(this.age); //6
super.age=12;
console.log(super.age,this.age); //undefined,12
}
}
let n1a=new n1();
第一个打印:在设置super后,n1本身没有this.age属性,那么这时打印的是原型链上父类的this.age
第二个打印:这里给this.age赋值了6,那么打印的时候自然就获得了6
第三个打印:在打印之前,这里不是用this.age赋值了,用了super.age赋值,这时的super等同于this,规范就是这么规定的,但是打印结果的时候super.age变成了undefined,是因为,这里的调用,super.age等同于了n.prototype.age,但是n没有age属性,所以打印成了undefined,我是这么理解的,赋值操作的时候,super等同与this,调用的时候等同于prototype。
detele不能删除通过super的父类
class m{
constructor(){}
age(){return 18}
}
class m1 extends m{
constructor(){
super()
}
age(){
console.log(super.age());
}
delage(){
delete super.age(); //无效果
}
}
let m1a=new m1();
m1a.delage();
m1a.age()
另一种extends
重申一下,ES6的class只是一种语法糖,本质上和ES5原型对象没有什么区别,只是为了语法更简单更简洁
就是之前说的ES6的新方法,setPrototypeOf()
setPrototypeOf(a,b)就是将b设置成a的原型对象等同
- a extends b
- let a =new b()
推荐阅读
-
JavaScript中的原型继承基础学习教程
-
聊聊那些使用前端Javascript实现的机器学习类库
-
从零开始学习前端JAVASCRIPT — 12、JavaScript面向对象编程
-
从零开始学习前端JAVASCRIPT — 14、闭包与继承()
-
从零开始学习前端JAVASCRIPT — 11、JavaScript运动模型及轮播图效果、放大镜效果、自适应瀑布流
-
从零开始学习前端JAVASCRIPT — JavaScript中this指向的四种情况
-
从零开始学习前端JAVASCRIPT — 8、JavaScript基础RegExp(正则表达式)
-
javascript 继承学习心得总结
-
从零开始学习前端JAVASCRIPT — 3、JavaScript基础Math和Date对象的介绍
-
web前端开发学习路线是怎样的?html+css+JavaScript的学习方法