JS的几种继承方式
Jonnzer Lv4

我们来谈谈JS的继承吧

原型链继承

方式 son.prototype = new father()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
function grandFather() {
this.gF_paroperty = 'gF_paroperty'
}
grandFather.prototype.getGFPropery = function() { // 祖父原型的方法
return this.gF_paroperty
}
function father() {
this.fatherPropery = 'fatherPropery'
}

// 建立 grandFather 和 father 的 连接 让父亲继承祖父(核心)
father.prototype = new grandFather();

father.prototype.getFatherVal = function() { // 父亲原型的方法
return this.fatherPropery;
}

var sonInstance = new father() // 儿子继承父亲
console.log(sonInstance.getGFPropery()); // expect output : 'gF_paroperty'
console.log(sonInstance.getFatherVal()); // expect output : fatherPropery

方法缺陷: 多个子实例会改变引用类型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function SuperType(){
this.colors = ["red", "blue", "green"];
}
function SubType(){}

SubType.prototype = new SuperType();

var instance1 = new SubType();
instance1.colors.push("black");
console.log(instance1.colors); //"red,blue,green,black"

var instance2 = new SubType();
console.log(instance2.colors); //"red,blue,green,black"

console.log(instance2.__proto__.colors) // array[4]

检测是否属于原型上的实例

  • instanceof :
    运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上。返回布尔。

最高级对象是 Object

1
2
3
4
5
6
7
var myString  = new String();
myString instanceof String; // 返回 true
myString instanceof Object; // 返回 true

[] instanceof Array // true
[] instanceof Object // true
{} instanceof Object // true

  • hasOwnProperty :
    检测自身原型上是否有传入参数的属性,返回布尔
    1
    2
    3
    4
    5
    const object1 = {};
    object1.property1 = 42;
    console.log(object1.hasOwnProperty('property1')); // true
    console.log(object1.hasOwnProperty('toString')); // false
    console.log(object1.hasOwnProperty('hasOwnProperty')) // false

构造函数 结合call继承

描述:核心代码是SuperType.call(this),创建子类实例时调用SuperType构造函数,于是SubType的每个实例都会将SuperType中的属性复制一份

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function  SuperType(){
this.color=["red","green","blue"];
}
SuperType.prototype.specialWay = '123'

function SubType(){
//继承自SuperType
SuperType.call(this);
}
var instance1 = new SubType();
instance1.color.push("black");
// alert(instance1.color);//"red,green,blue,black"

var instance2 = new SubType();
// alert(instance2.color);//"red,green,blue"
console.log(instance2.specialWay); // output:undefined 原型上的属性、方法继承不了
(1) 只能继承父类的实例属性和方法,不能继承原型属性/方法 (2) 无法实现复用,`每个子类都有父类实例函数的副本`,影响性能

Object.create

也就是提供一个返回一个新对象,并且该对象的__proto__指向传入的对象
语法

1
2
3
4
Object.create(proto[, propertiesObject])

// 比较好的用法👍
son.prototype = Object.create(father.prototype)
1
2
3
4
5
6
// 原理
function object(obj){
function F(){}
F.prototype = obj;
return new F();
}
(1) 原型链继承多个实例的引用类型属性指向相同,存在篡改的可能。 (2) 无法传递参数

ES6 class extends super

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Rectangle { // class 名一般都是大写开头
constructor(height, width) {
this.height = height;
this.width = width;
}
get area() { // Getter
return this.calcArea()
}

calcArea() { // Method
return this.height * this.width;
}
}

const rectangle = new Rectangle(10, 20);
// 输出 200
console.log(rectangle.area);
  • class 的 继承 extends 关键字

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    // 继承
    class Square extends Rectangle {
    constructor(length) {
    super(length, length);
    this.name = 'Square'; // 如果子类中存在构造函数,则需要在使用“this”之前首先调用 super()。
    }
    get area() {
    return this.height * this.width;
    }
    }
    const square = new Square(10);
    console.log(square.area);
    // 输出 100

  • class 实际上是函数的语法糖🍬

    1
    2
    typeof Rectangle // 'function'
    typeof Square // 'function'

ES5继承和ES6继承的区别

  • ES5的继承实质上是先创建子类的实例对象,然后再将父类的方法添加到this上(Parent.call(this)).
  • ES6的继承有所不同,实质上是先创建父类的实例对象this,然后再用子类的构造函数修改this。
    因为子类没有自己的this对象,所以必须先调用父类的super()方法,否则新建实例报错。

参考链接:
掘金
es6 阮一峰 class getter setter
mdn instanceof

  • 本文标题:JS的几种继承方式
  • 本文作者:Jonnzer
  • 创建时间:2020-04-07 17:20:35
  • 本文链接:https://jonnzer.github.io/2020/04/07/JS/继承/
  • 版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
 评论