javascript中类的继承方式解析

MDN上类的继承方式

上一篇说了js中的实例化,这篇说一下js中的类的继承方式
经常能搜到一些总结js继承方式的文章,原型链继承,构造函数继承,组合继承,寄生继承,组合寄生继承, 新手看完之后肯定是越看越懵逼,这些文章写到最后一定是推荐使用组合寄生继承,因为只有这种方式是最完美的。
这篇咱们不看那么多,只看前端的圣经,MDN上是如何实现类继承的。

MDN上只说了单继承和多继承,很好理解,单继承就是只有一个父类,多继承就是有多个父类

首先要明确的概念,对象的属性和方法在js中其实都可以看作是属性,方法是值为函数的属性。下面说到的属性二字都包括方法。

实例属性是每个实例所独有的,不应该受到其他实例影响,换个说法就是实例属性不能是引用关系。

原型属性则是所有实例所公用的,这也正是类存在的意义:实现部分属性的复用,从而减少代码量,提高性能,并且更加符合人类对于事物的抽象认知,也就是面向对象。
所以原型属性是引用关系。

以下代码粘贴自MDN,部分汉字为我加的注释

// 单继承
// Shape - 父类(superclass)
function Shape() {
  this.x = 0;
  this.y = 0;
}

// 父类的方法
Shape.prototype.move = function(x, y) {
  this.x += x;
  this.y += y;
  console.info('Shape moved.');
};

// Rectangle - 子类(subclass)
function Rectangle() {
	// new Rectangle()时就会把父类代码里的this.x = 0;this.y = 0;引入到这里
	// 同时this指向的是子类的上下文,实现实例属性的继承
  Shape.call(this); // call super constructor.
}

// 子类续承父类
Rectangle.prototype = Object.create(Shape.prototype);
// Shape.prototype.constructor是 Shape
// 如果不修正的话,Rectangle.prototype.constructor也会变成Shape,显然不符合常理
Rectangle.prototype.constructor = Rectangle;

var rect = new Rectangle();

console.log('Is rect an instance of Rectangle?',
  rect instanceof Rectangle); // true
console.log('Is rect an instance of Shape?',
  rect instanceof Shape); // true
rect.move(1, 1); // Outputs, 'Shape moved.'

懂得的同学看完以后就会说:这不就是组合寄生式继承么。

Shape.call(this) 这句代表组合
Rectangle.prototype =Object.create(Shape.prototype) 这句代表寄生
组合可以理解为没有引用关系,属性之间都是独立的
寄生可以理解为子类复用父类的属性

rect.move === Shape.prototype.move // true

当然,MDN不会搞这么变态的一个名字来命名它。你只需要知道这种方式就是正统写法,当然其他的方式最好也要理解,但不要被搞懵逼了。

代码分析

许多同学会有疑问,其中这一句

Rectangle.prototype = Object.create(Shape.prototype);

可以写成下面这样么?

Rectangle.prototype = Shape.prototype

你可以这么改写一下,把代码复制到控制台,执行以后返回的结果仍然是符合预期的。

区别就是如果这么写了,这两个原型就会是一种引用关系!

当修改Rectangle.prototype.move = xxx 时,Shape.prototype.move 也会被修改。

如果按正统写法Rectangle.prototype = Object.create(Shape.prototype),
当修改Rectangle.prototype.move = xxx 时,Shape.prototype.move仍会保持原来的值,更加符合我们的常规需求。
也就是子类可以重写父类的同名属性。

于是Object.create的作用就很好理解了,就是把Shape.prototype这个对象在原型链上向上推了一层,并且重新生成一个对象。

多继承

接下来还有类的多继承,如果上面的理解了,多继承就没啥说的了。
如果用组合寄生的概念来解释,那就是多组合,多寄生。
Object.assign把多个父类原型合并一下,赋值给子类的原型。
代码如下

function MyClass() {
    SuperClass.call(this);  // 多组合
     OtherSuperClass.call(this);
}


MyClass.prototype = Object.create(SuperClass.prototype);
// 多寄生
Object.assign(MyClass.prototype, OtherSuperClass.prototype);

MyClass.prototype.constructor = MyClass;

MyClass.prototype.myMethod = function() {
     // do a thing
};

es6里extends就不说了,实际上就是这种继承方式的语法糖。

欢迎来我的b站空间逛逛
https://space.bilibili.com/395672451

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值