js继承的这6种方式!(上)

js继承的这6种方式!(上)

什么是继承?

在面向对象编程中,继承是指一个新类从一个现有的类继承了一些方法和属性。被继承的类称为父类(或基类、超类),新类称为子类(或派生类)。

继承的好处

  • 可以使用父类已经定义好的属性和方法,减少重复的代码;
  • 提高代码的可扩展性和可维护性。

继承的6种方式

下面,让我们逐个详细介绍js中的6种继承方式。

1. 原型链继承

原型链继承是常见的继承方式,它的本质是重写原型对象。我们可以在父类的原型上定义实例方法或属性,这样子类也能够访问和使用这些方法或属性。

function Parent() {
    this.name = ['John', 'Mary'];
}
Parent.prototype.getName = function() {
    return this.name;
};

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

var child1 = new Child();
console.log(child1.getName()); // ['John', 'Mary']

注:当我们在子类中调用 getName方法的时候,实际上它是通过在原型链上查找到父类的 getName方法并被调用的。

但是需要注意的是,如果在子类实例中修改了继承的数组 name,那么这个修改会影响到父类和其他子类,这样会产生一些难以预知的问题。因此,原型链继承主要存在如下缺点:

  1. 无法传递参数。如果子类想对父类的构造函数传递一些参数,那么必须修改子类的原型对象或者通过另外的方式来实现;
  2. 共享引用类型的属性。原型链继承会使子类实例共享父类实例创建的引用类型的属性。这导致子类实例间存在一个难以分离的引用。

2. 构造函数继承

构造函数继承也叫做经典继承,它的本质是在子类的构造函数中调用父类的构造函数,并用它的证书属性来扩展子类的实例。

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

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

var child1 = new Child('John');
console.log(child1.getName()); // 'John'

注:在 Child函数内部,我们调用了Parent构造函数并改变了它的this值。这样就能通过子类的实例 child1 来访问来自父类的属性或方法了。

构造函数继承虽然弥补了原型链继承的短板,例如子类实例共享父类实例的问题,但是它也存在一些缺点:

  1. 父类的方法没有被复用,每个子类都有一个独立的方法实例;
  2. 只能继承父类的实例属性,不能继承父类的原型属性和方法。这使得构造函数继承无法实现函数复用,导致子类实例之间不能共享方法和属性。

3. 组合继承

组合继承是常用的继承方式,它结合了原型链继承和构造函数继承的优点。

function Parent(name) {
    this.name = name;
    this.colors = ['red', 'green', 'blue'];
}
Parent.prototype.getName = function() {
    return this.name;
};

function Child(name, age) {
    Parent.call(this, name);
    this.age = age;
}
Child.prototype = new Parent();
Child.prototype.constructor = Child;

var child1 = new Child('John', 18);
child1.colors.push('black');
console.log(child1.getName(), child1.age, child1.colors); // John 18 ['red', 'green', 'blue', 'black']

var child2 = new Child('Mary', 20);
console.log(child2.getName(), child2.age, child2.colors); // Mary 20 ['red', 'green', 'blue']

注:在 Child函数内部,我们调用了Parent构造函数并改变了它的this值。这样就能复用来自父类的方法实例了。同时又将父类的实例属性导入子类实例中,并通过继承父类的原型对象来使得子类也能使用来自父类的实例方法和原型方法。

组合继承是javascript中最常用的继承方式之一,但也存在缺点:每次在创建子类实例的时候,都会调用一次父类的构造函数导致原型链中存在多余的执行。

4. 原型式继承

原型式继承的核心是利用一个只用于临时对象创建的构造函数作为桥梁。本质上,就是对原型对象的继承。

function object(o) {
    function F(){}
    F.prototype = o;
    return new F();
}

var person = {
    name: 'John',
    colors: ['red', 'green', 'blue']
};

var child1 = object(person);
var child2 = object(person);
child1.colors.push('black');
console.log(child1.name, child1.colors); // 'John', ['red', 'green', 'blue', 'black']
console.log(child2.colors); // ['red', 'green', 'blue', 'black']

原型式继承通过一个工厂模式返回一个新对象,并在新对象与原型对象之间创建了一个关联。通过这种关联,子类可以访问原型对象的所有属性和方法。但是,与原型链继承相似的是,原型式继承也存在着与原型链继承相同的缺点。

5. 寄生式继承

寄生式继承是原型式继承的一种增强版,其本质是对原型式继承(或其他继承方式)的一种优化策略。

function object(o) {
    function F(){}
    F.prototype = o;
    return new F();
}

function createAnother(original) {
    var clone = object(original);
    clone.getColors = function() {
        return this.colors;
    };
    return clone;
}

var person = {
    name: 'John',
    colors: ['red', 'green', 'blue']
};

var child1 = createAnother(person);
var child2 = createAnother(person);
child1.colors.push('black');
console.log(child1.getColors()); // ['red', 'green', 'blue', 'black']
console.log(child2.getColors()); // ['red', 'green', 'blue']

注:在使用寄生式继承的过程中,我们可以在返回的对象上面添加额外的属性或方法,使其能够满足子类自身的需求。

寄生式继承相较于原型式继承,其可以引用传入的参数,相对于构造函数继承和组合继承,它的性能要更加的优秀。

6. 寄生组合式继承

虽然组合式继承结合了原型链继承和构造函数继承的优点,但也存在着问题,即在子类中会重复调用构造函数。

针对这个问题,我们可以使用寄生组合式继承来实现这个操作。寄生组合式继承先是利用父类的拷贝实现复制父类的实例属性和方法,然后在通过将子类原型指向父类的拷贝来继承父类原型的方法。

function inhertPrototype(subType, superType) {
    var prototype = Object.create(superType.prototype);
    prototype.constructor = subType;
    subType.prototype = prototype;
}

function Parent(name) {
    this.name = name;
    this.colors = ['red', 'green', 'blue'];
}
Parent.prototype.getName = function() {
    return this.name;
};

function Child(name, age) {
    Parent.call(this, name);
    this.age = age;
}
// 在此处完成了引用类型属性的复制
inheritPrototype(Child, Parent);

var child1 = new Child('John', 18);
child1.colors.push('black');
console.log(child1.getName(), child1.age, child1.colors); // John 18 ['red', 'green', 'blue', 'black']

var child2 = new Child('Mary', 20);
console.log(child2.getName(), child2.age, child2.colors); // Mary 20 ['red', 'green', 'blue']

寄生组合式继承是继承中的经典法属。相较于组合式继承,寄生组合式继承最大的优点就是避免了在使用组合式继承时对父类的呼叫。

以上就是js中的六种继承方式,可以根据不同的需求在实际开发中进行选择。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:js继承的这6种方式!(上) - Python技术站

(0)
上一篇 2023年6月26日
下一篇 2023年6月26日

相关文章

  • 微信“xxx撤回了一条消息并亲了你一下”玩法教程

    微信“xxx撤回了一条消息并亲了你一下”玩法教程 简介 微信“xxx撤回了一条消息并亲了你一下”是一种有趣的玩法,可以给聊天对方带来惊喜和乐趣。当你撤回一条消息时,会自动发送一条“xxx撤回了一条消息并亲了你一下”的提示消息,并附带一个亲吻表情。下面是详细的攻略教程。 步骤 发送消息:首先,你需要发送一条消息给聊天对方。可以是文字、图片、表情等任意类型的消息…

    other 2023年8月6日
    00
  • pythonmysql模块

    pythonmysql模块 Python是一门高级编程语言,它被广泛地应用于各个领域。在Web开发中,Python是最常用的编程语言之一。Python通过pip工具提供了丰富的第三方模块,可以大幅度提升开发效率和开发质量。 本文主要介绍Python中的mysql模块,它是Python中操作MySQL数据库的主要工具。 安装mysql模块 在使用mysql模块…

    其他 2023年3月29日
    00
  • PHP中$GLOBALS与global的区别详解

    PHP中$GLOBALS与global的区别详解 在PHP中,$GLOBALS和global都是用于在函数内部访问全局变量的关键字。它们的作用相似,但有一些重要的区别。 1. $GLOBALS关键字 $GLOBALS是一个超全局变量,它是一个包含了当前脚本中所有全局变量的关联数组。通过$GLOBALS可以在函数内部访问和修改全局变量的值。 下面是一个示例,演…

    other 2023年7月29日
    00
  • Android嵌套线性布局玩法坑解决方法

    Android嵌套线性布局玩法坑解决方法攻略 在Android开发中,使用线性布局(LinearLayout)进行UI设计是非常常见的。然而,当我们需要在一个线性布局中嵌套另一个线性布局时,可能会遇到一些问题和坑。本攻略将详细讲解Android嵌套线性布局的玩法,并提供解决方法。 问题描述 当我们在一个线性布局中嵌套另一个线性布局时,可能会出现以下问题: 布…

    other 2023年7月28日
    00
  • Java超详细分析继承与重写的特点

    Java超详细分析继承与重写的特点攻略 什么是继承 继承是面向对象编程中的重要特性之一,它允许一个类继承另一个类的属性和方法。继承的类称为子类,被继承的类称为父类。在Java中,使用关键字extends来实现继承。 继承的特点 继承具有以下特点: 子类可以继承父类的非私有属性和方法。 子类可以在不改变父类的情况下扩展其功能。 父类的私有属性和方法不会被子类继…

    other 2023年6月26日
    00
  • PowerShell小技巧之使用New-Module命令动态创建对象

    以下是使用标准的Markdown格式文本,详细讲解PowerShell中使用New-Module命令动态创建对象的完整攻略: PowerShell小技巧之使用New-Module命令动态创建对象 1. New-Module命令简介 New-Module命令是PowerShell中的一个强大工具,用于动态创建自定义的对象。通过New-Module命令,您可以定…

    other 2023年10月14日
    00
  • Windows Server 2019和Windows Server, Version 1909的区别是什么

    Windows Server 2019和Windows Server, Version 1909是微软公司发布的两个Windows Server产品,它们之间存在一些区别和特性。本文将详细讲解它们之间的区别和如何选择。 区别 产品版本 Windows Server 2019是微软公司发布的最新版本,它是Windows Server产品系列的第九个主要版本。而…

    other 2023年6月27日
    00
  • 织梦中arclist调用附加字段的方法

    使用织梦(DedeCMS)时,我们可以添加一些自定义的附加字段(如作者、副标题、来源等)来丰富文章内容。当需要调用这些附加字段时,我们可以采用arclist调用的方式。 以下是调用附加字段的步骤: 在文章发布时,添加附加字段 首先,我们需要在文章发布页面中添加附加字段。我们可以进入“织梦管理后台”->“内容管理”->“文章发布”,在该页面下方可以…

    other 2023年6月25日
    00
合作推广
合作推广
分享本页
返回顶部