JavaScript面向对象之继承 (上)

本文深入探讨JavaScript中的原型链继承、借用构造函数继承及组合继承三种继承模式,详细讲解每种模式的特点、优缺点及适用场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

原型链继承

我们再通过前几篇的例子再了解下原型链继承

//创建自定义构造函数
function Person() {
    this.name = "姓名";
}
//在当前构造函数的原型链上添加属性hobby
Person.prototype.hobby = "旅游"

//通过自定义构造函数Person实例化一个对象LJJ
const LJJ = new Person()
console.log(LJJ.hobby) // 旅游
//通过自定义构造函数Person实例化一个对象YH
const YH = new Person()
console.log(YH.hobby) // 旅游

从例字中 我们看到,LJJ与YH都从Person那里继承到了hobby “旅游”, 那我们继续往下看

//创建自定义构造函数
function Person() {
    this.name = "姓名";
}
//在当前构造函数的原型链上添加属性hobby
Person.prototype.hobby = "旅游"

//通过自定义构造函数Person实例化一个对象LJJ
const LJJ = new Person()
LJJ.hobby = "敲代码"
console.log(LJJ.hobby) // 敲代码
//通过自定义构造函数Person实例化一个对象YH
const YH = new Person()
console.log(YH.hobby) // 旅游

对LJJ的hobby重新赋值并没有影响YH的hobby,然后我们打印下LJJ;
输出:
在这里插入图片描述
LJJ的hobby屏蔽了原型链上的hobby,所以LJJ的hobby是"敲代码",而YH的hobby仍然是原型上的hobby"旅游"
我们再换一种写法,看代码:

function Person() {
    this.name = "姓名"
}
Person.prototype.hobby = ["旅游","看电影"]

const LJJ = new Person()
LJJ.hobby.push("敲代码") 
console.log(LJJ.hobby) // ["旅游", "看电影","敲代码"]
const YH = new Person()
//构造函数中的hobby已经被改变
console.log(YH.hobby) // ["旅游", "看电影","敲代码"]

因为在实例LJJ中添加引用类型导致改变了构造函数Person的hobby属性,因为LJJ与YH是Person的实例,都继承了Person的属性,所以Person的属性改变直接影响了他的实例;因此引入引用类型时应注意,我前面有一篇讲到了处理方法,但今天我们用另一种来解决

借用构造函数

借用?就是使用call或者apply改变一下this指向,
就是子类的构造函数内部通过call或者apply调用父类的构造函数,如果对call方法有不了解的地方,可以翻看昨天的文章

//创建一个构造函数,并添加一些属性
function Person() {
    this.name = "姓名"
    this.nickName = "昵称"
    this.hobby = ["爱好"]
}
//创建一个构造函数,并借用了Person的构造函数
function Ljj() {
        Person.call(this)
        this.name = "刘家军"
        this.hobby = ["旅游","敲代码"]
}
//创建一个构造函数,并借用了Person的构造函数
function Yh() {
    Person.call(this)
    this.name = "袁姮"
    this.hobby = ["旅游","看电影"]

}
const LJJ= new Ljj();
console.log(LJJ);

const YH = new Yh();
console.log(YH);

输出:
在这里插入图片描述
这样就避免了原型链继承中,构造函数中的属性或者方法被其他实例所改变的问题
但要注意一下代码执行顺序,不要被后面的代码覆盖了前面的代码,一般情况我们用到call()方法直接写在函数的第一行

借用构造函数进行传参

function Person(name,hobby) {
  this.name = name;
  this.hobby = hobby
}
function Ljj() {
  Person.call(this,"刘家军",["旅游","敲代码"])
}

function Yh() {
  Person.call(this,"袁姮",["旅游","看电影"])
}
const LJJ = new Ljj();
console.log(LJJ);

const YH = new Yh();
console.log(YH);

输出:
在这里插入图片描述

组合继承

将原型链和借用构造函数技术组合到一起。
使用原型链实现对原型属性和方法的继承,用借用构造函数模式实现对实例属性的继承。
这样既通过在原型上定义方法实现了函数复用,又能保证每个实例都有自己的属性

function Person(name) {
  this.name = name
  this.hobby = ["旅游","看电影"]
}
function CallThis(name) {
  Person.call(this, name)
}
CallThis.prototype = new Person();

let LJJ = new CallThis("刘家军")
LJJ.hobby.push("敲代码")
console.log(LJJ);
let YH = new CallThis("袁姮")
console.log(YH);

输出:
在这里插入图片描述
我们把这个组合继承和之前的两个原型链继承和借用构造函数继承进行比较
不难发现组合继承融合了他们的优点,成为javascript中最常用的继承模式
预知后事如何,且听下次分解

友情链接:点击查看所有文章目录

友情连接:点击查看 JavaScript面向对象系列文章目录

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

刘家军

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值