10分钟搞懂js五种继承

作者: mytac | 来源:发表于2020-07-01 17:52 被阅读0次

前言

为了更好的阅读体验你可以查看我的github原文

最近又要面试了,继承这块掌握的不扎实,今天写出来好好研究研究。

1. 原型继承

核心思想

Child.prototype = new Parent();

子类的原型指向父类的一个实例,即子类的 protytype 指向父类实例的__proto__,所以子类实例就继承了父类原型上的属性和方法。

举例

function Foo(name = "foo") {
  this.name = name;
  this.array = [];
}
Foo.prototype.name = "tom";

function Child() {}
Child.prototype = new Foo();

const child = new Child("child1");
child.array.push(1);

const child2 = new Child("child2");
child2.array.push(2);
console.log(child.constructor.array == Foo.prototype.array); //true
console.log("child", child2.array); //[1,2]
console.log(child2.name); //foo

缺点

我们参考上例,

  1. 每个 child 实例中的 array 属性所指向的都是Foo.prototype.array,因此对于引用类型的存储都指向同一块内存,child1 和 child2 的 array 是共享的,并不是独立的。
  2. 直接将子类的原型指向父类的实例,子类实例无法初始化父类构造函数上的属性。参考上例,每个 child 实例都不能给父类上的 name 属性赋值。

2.构造函数继承

核心思想

function Child() {
  Foo.apply(this, arguments);
}
Child.prototype = new Parent();

在子类的构造函数中,通过改变父类构造函数的执行上下文,相当于做了代理。

举例

function Foo(name = "foo") {
  this.name = name;
  this.array = [];
}
Foo.prototype.age = 18;

function Child() {
  Foo.apply(this, arguments);
}

const child = new Child("child");
child.array.push(1);
console.log(child.name); // child
console.log(child.age); // undefined prototype上的属性没有继承

const child2 = new Child("child2");
child2.array.push(2);
console.log(child2.array); // [2] 独立的实例

缺点

  1. prototype 上的属性和方法没有继承。适合没有在父类原型链上自定义方法和属性的继承。

3. 组合继承

核心思想

function Child() {
  Foo.apply(this, arguments);
}
Child.prototype = new Parent();

其实就是把上面两种思想结合起来。

举例

function Foo(name = "foo") {
  this.name = name;
  this.array = [];
}
Foo.prototype.sayName = function () {
  console.log(this.name);
};

function Child() {
  Foo.apply(this, arguments);
}

Child.prototype = new Foo();

const child = new Child("child");
child.array.push(1);

const child2 = new Child("child2");
child2.array.push(2);

console.log(child2.array); // [2] 没有共享,实例里面的属性都是独立的
child2.sayName(); // child2 可以继承父类原型上的方法与属性

缺点

调用了两次构造函数。可能你会奇怪,为什么两种组合起来,反而两者的缺陷都解决了。这是因为在访问实例的时候,先找实例自身的属性,然后才回顺着原型链一级一级找原型上的属性,直至找不打返回 undefined。

4.寄生组合

核心思想

需要浅拷贝父类对象,来解决不能访问父类原型属性的问题。

function Child() {
  Foo.apply(this, arguments);
}
Child.prototype = Object.create(Parent.prototype);
Child.prototype.constructor = Parent;

实例

function Foo(name = "foo") {
  this.name = name;
  this.array = [];
}
Foo.prototype.sayName = function () {
  console.log(this.name);
};

function Child() {
  Foo.apply(this, arguments);
}

Child.prototype = Object.create(Foo.prototype);
Child.prototype.constructor = Child; //注意这一句,如果不加,子类实例的constructor指向Foo

const child = new Child("child");
child.array.push(1);
console.log(child.name);

const child2 = new Child("child2");
child2.array.push(2);
console.log(child2.array); // [2] 没有共享,实例里面的属性都是独立的
child2.sayName(); // child2 可以继承父类原型上的方法与属性

缺点

几乎没有,但要非找个缺点,需要浅拷贝父类的原型,浪费内存。。

5. extends 继承

开发时首选,不多说了。现代人谁还拿 prototype 写继承?

class Foo {
  constructor(name = "foo") {
    this.name = name;
    this.array = [];
  }
  sayName() {
    console.log(this.name);
  }
}

class Child extends Foo {
  constructor(name) {
    super(name);
  }
}

const child = new Child("child");
child.array.push(1);
console.log(child.name); // child

const child2 = new Child("child2");
child2.array.push(2);
console.log(child2.array); // [2] 没有共享,实例里面的属性都是独立的
child2.sayName(); // child2 可以继承父类原型上的方法与属性

缺点

没有缺点,要是有非说不适配浏览器啥的,那就是工程化不及格。

关注我的订阅号获得更加及时的推送~

wechat:那屋水泡

相关文章

  • 搞懂 JavaScript 继承原理

    摘要: 理解JS继承。 原文:搞懂 JavaScript 继承原理 作者:前端小智 Fundebug经授权转载,版...

  • JS中的原型和原型链详解

    JS中的原型和原型链是大家彻底搞懂JS面向对象及JS中继承相关知识模块非常重要的一个模块,一旦突破这块知识点,相信...

  • Js的继承

    js的继承 @(js)[继承, js, 前端] 组合继承是原性链继承和构造函数继承的合体,它汲取了二者各自的有点,...

  • 一文搞懂js中的继承

    原型链继承(Prototypal inheritance) 1. [[Prototype]] (对象的属性) [[...

  • JS继承

    JS中的继承 许多OO语言都支持两种继承方式:接口继承和实现继承; 因为JS中没有类和接口的概念 , 所以JS不支...

  • #js继承

    js继承的概念 js里常用的如下两种继承方式: 原型链继承(对象间的继承)类式继承(构造函数间的继承) 类式继承是...

  • 前端知识点

    JS 1. 事件循环 「硬核JS」一次搞懂JS运行机制[https://juejin.cn/post/684490...

  • js继承遇到的小问题

    这两天在看js继承方面,它不像OC那种传统的类继承。js继承方式还是挺多的。比如:原型继承、原型冒充、复制继承 原...

  • 10分钟搞懂js五种继承

    前言 为了更好的阅读体验你可以查看我的github原文 最近又要面试了,继承这块掌握的不扎实,今天写出来好好研究研...

  • JS中继承的实现

    JS中继承的实现 #prototype (js原型(prototype)实现继承) 全局的Function对象没有...

网友评论

    本文标题:10分钟搞懂js五种继承

    本文链接:https://www.haomeiwen.com/subject/szehqktx.html