JavaScript es6 五种常见继承方式

前言

参考:
原型和原型链
原型继承和 Class 继承
B站讲解

原型链

实例对象的隐式原型__proto__指向函数对象的显式原型prototype,原型的最终指向是Object的null

当我们使用一个对象的属性和方法时,先从自身找,如果找不到则去原型对象proto中寻找,如果原型对象也找不到,则去原型的原型对象中寻找,直到找到Object的原型对象为止,这个链式查找的过程我们称为原型链.

原型链不一定只有一条

JavaScript es6 五种常见继承方式_第1张图片

原型链继承

function Parent() {
  //父类
  this.colors = ["red", "yellow"];
}

function Child() {
  //子类
}

Child.prototype = new Parent();
let result = new Child(); //result是child的实例对象
console.log(result.colors);
result.colors.push("pink");
console.log(result.colors);

JavaScript es6 五种常见继承方式_第2张图片
缺点:
1、多个实例对引用类型的操作会被篡改
2、子类型的原型上的 constructor 属性被重写了
3、给子类型原型添加属性和方法必须在替换原型之后
4、创建子类型实例时无法向父类型的构造函数传参

构造函数继承

// 问题:每次去执行子类的时候就会创建父类的方法
function Parent(name) {
  this.colors = ["red", "white"];
  this.name = name;
  this.getName = function getName() {
    return this.name;
  };
}
function Child(name) {
  Parent.call(this, name);
}

let res = new Child("army");
console.log(res.name, res.colors);
let res2 = new Child("patty");
res2.colors.push("pink");
console.log(res2.name, res2.colors);

JavaScript es6 五种常见继承方式_第3张图片

组合继承

function Parent(name) {
  this.colors = ["red", "white"];
  this.name = name;
}
Parent.prototype.getName = function () {
  return this.name;
};
function Child(name) {
  Parent.call(this, name);
}
Child.prototype = new Parent();
Child.prototype.construcor = Parent;
const res = new Child("hello");
// child.getValue();
console.log(res.name);
let res2 = res instanceof Parent; // true
console.log(res2);
/*以上继承的方式核心是在子类的构造函数中通过 Parent.call(this) 继承父类的属性
然后改变子类的原型为 new Parent() 来继承父类的函数。
这种继承方式优点在于构造函数可以传参,不会与父类引用属性共享,可以复用父类的函数,
但是也存在一个缺点就是在继承父类函数的时候调用了父类构造函数,
导致子类的原型上多了不需要的父类属性,存在内存上的浪费。

 */

JavaScript es6 五种常见继承方式_第4张图片

寄生组合继承

function Parent(name) {
  this.name = name;
  this.colors = ["red", "yellow"];
}

Parent.prototype.getName = function () {
  return this.name;
};

function Child(name) {
  Parent.call(this, name);
}

Child.prototype = Object.create(Parent.prototype, {
  constructor: {
    value: Child,
    enumerable: false,
    writable: true,
    configurable: true,
  },
});

const child = new Child("李四");
console.log(child.name);
let res = child.getName();
console.log(res);
let res2 = child instanceof Parent;
console.log(res2);

JavaScript es6 五种常见继承方式_第5张图片

class继承

class Parent {
  constructor(val) {
    this.name = val;
    this.colors = ["red", "yellow"];
  }
  getName() {
    console.log(this.name);
  }
}
// class 实现继承的核心在于使用 extends 表明继承自哪个父类,
// 并且在子类构造函数中必须调用 super,因为这段代码可以看成 Parent.call(this, value)。
class Child extends Parent {
  constructor(value) {
    super(value);
    this.name = value;
  }
}
let child = new Child("李四");
console.log(child.colors);
let res = child.getName();
let res2 = child instanceof Parent;
console.log(res2);
let res3 = Parent instanceof Function;
console.log(res3); // js不存在类,所以class本质就是函数

JavaScript es6 五种常见继承方式_第6张图片

你可能感兴趣的:(web前端,javascript,es6,原型模式)