js中类的继承--extends

什么是类的继承

创建类继承,需要使用 extends关键字。

使用类继承创建的类继承了另一个类的所有方法
官网代码示例

class Car {
  constructor(brand) {
    this.carname = brand;
  }
  present() {
    return 'I have a ' + this.carname;
  }
}

class Model extends Car {
  constructor(brand, mod) {
    super(brand);
    this.model = mod;
  }
  show() {
    return this.present() + ', it is a ' + this.model;
  }
}

let myCar = new Model("Ford", "Mustang");
document.getElementById("demo").innerHTML = myCar.show();

在Model的构造方法中我们看到了super(),通过在 constructor 方法中调用 super() 方法,我们调用了父级的 constructor 方法获得了父级的属性和方法的访问权限

继承对于代码可重用性很有用:在创建新类时重用现有类的属性和方法。

getter和setter的实现

如需在类中添加 getter 和 setter,需使用 get set 关键字。
注意:即使 getter 是一个方法,当你想要获取属性值时也不要使用括号。
getter/setter 方法的名称不能属性名称相同,许多程序员在属性名称前使用下划线字符 _ 将 getter/setter 与实际属性分开:

class Car {
  constructor(brand) {
    this._carname = brand;
  }
  get carname() {
    return this._carname;
  }
  set carname(x) {
    this._carname = x;
  }
}

let myCar = new Car("Ford");
myCar.carname = "Volvo";//直接通过.访问
document.getElementById("demo").innerHTML = myCar.carname;

区别 优势
getter和setter提供了更多的优势和灵活性:

封装(Encapsulation):通过getter和setter,可以隐藏内部实现细节,只暴露必要的接口。这有助于保护对象内部状态的完整性,并允许开发者更改属性的内部结构而不影响到类的使用者。

计算属性(Computed Properties):getter可以用来返回一个计算值,而不仅仅是存储的值。这意味着你可以根据对象的其他属性动态计算属性值。

验证和控制(Validation and Control):setter可以允许你在属性值被设置前进行验证或转换,确保对象处于有效状态,或者执行相关的副作用。

懒加载(Lazy Loading):可以利用getter实现属性值的懒加载,即只有在首次访问时才计算属性值,然后将其缓存起来。

日志和调试(Logging and Debugging):如果需要跟踪属性的访问或修改,getter和setter是很好的切入点来添加日志记录逻辑。
例子

class Person {
  constructor(firstName, lastName) {
    this.firstName = firstName;
    this.lastName = lastName;
    // fullName 直接作为属性存在,但没有额外逻辑
    this.fullName = `${firstName} ${lastName}`;
  }
}

const person = new Person('John', 'Doe');

// 直接访问fullName属性
console.log(person.fullName); // 输出:John Doe

// 尝试直接更新fullName属性
person.fullName = 'Jane Smith';

// 由于我们没有在设置fullName时更新firstName和lastName,所以这里还是原来的值
console.log(person.fullName); // 输出:Jane Smith
console.log(person.firstName); // 输出:John
console.log(person.lastName); // 输出:Doe

在这个例子中,fullName 是作为一个普通属性存在的,当fullName被直接设置时,并不会影响firstName和lastName的值,反之亦然。这说明了为什么可能需要getter和setter来同步更新相关联的属性值。

总的来说,尽管getter和setter不是必须的,但它们提供了一种更强大、可控的方式来管理对象属性的访问和修改。

Hoisting

与函数和其他 JavaScript 声明不同,类声明不会被提升。

这意味着必须先声明类,然后才能使用它:

/您还不能使用该类。
//myCar = new Car("Ford")
//This would raise an error.

class Car {
  constructor(brand) {
    this.carname = brand;
  }
}

//现在您可以使用该类:
let myCar = new Car("Ford")

对于其他声明,如函数,在声明之前尝试使用它时不会出错,因为 JavaScript 声明的默认行为是提升(将声明移到顶部)。

super()

让我们把super()说的更加详细一些
super据我目前理解,有两个作用:
1.调用父类的构造函数
2.为父类的构造函数传参

如果父类的构造函数需要参数并且没有为这些参数提供默认值,但是你在子类中调用 super() 时没有传递任何参数,这将导致运行时错误。更具体地说,它会抛出一个 TypeError,因为父类期望得到一些参数,而实际上没有收到。

下面是一个示例来展示这种情况:

class Parent {
  constructor(a, b) {
    // 父类构造函数需要两个参数
    this.a = a;
    this.b = b;
  }
}

class Child extends Parent {
  constructor() {
    super(); // 调用父类构造函数但不传递任何参数
    // 子类特有的初始化代码...
  }
}

// 尝试创建Child类的实例
const myChild = new Child();

这样在调用父类构造函数的时候就会发生问题
解决这个问题通常有两个方法:

  • 修改父类构造函数,为其参数提供默认值。
比如 constructor(length, width, height, track_id = undefined) {}
这是es6的一个新特性,此处在没有传入参数时候,默认为undefined
  • 在子类中调用 super() 时确保传递所有必需的参数。

如果无法修改父类或者确实不想在子类中使用父类的初始化逻辑,那么可能需要重新考虑是否应该使用继承,或者寻找其他设计模式(例如组合)来满足需求了。

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
JavaScript 中,继承是一个非常常见的概念。ES6 引入了 Class 语法糖,让继承更加易于理解和实现。在 Class 中,我们可以使用 extends 关键字来创建一个子类,使其继承父类的属性和方法。 下面我们来详细了解一下如何在 JavaScript 中使用 extends 实现继承。 ### 基础语法 首先,我们需要定义一个父类。在 ES6 中,我们可以使用 Class 来定义一个类。例如: ```javascript class Animal { constructor(name) { this.name = name; } speak() { console.log(this.name + ' makes a noise.'); } } ``` 这个 Animal 类有一个构造函数和一个 speak 方法。构造函数会在创建实例时被调用,而 speak 方法则可以让动物发出一些声音。 接下来,我们来创建一个子类。使用 extends 关键字来创建子类,并使用 super() 方法调用父类的构造函数。例如: ```javascript class Dog extends Animal { constructor(name) { super(name); } speak() { console.log(this.name + ' barks.'); } } ``` 这个 Dog 类继承了 Animal 类,并覆盖了其 speak 方法。在构造函数中,我们通过 super() 方法来调用父类的构造函数,并将传递的参数传递给它。 现在,我们可以创建一个 Dog 的实例,并调用其 speak 方法: ```javascript let d = new Dog('Mitzie'); d.speak(); // Mitzie barks. ``` ### 继承父类的方法 当一个子类继承了一个父类时,它会继承父类的属性和方法。例如,在上面的例子中,Dog 类继承了 Animal 类,因此它继承了 Animal 类的 speak 方法。 当我们调用子类的方法时,如果子类没有实现该方法,它会自动调用父类的方法。例如,在上面的例子中,如果我们不覆盖 Dog 类的 speak 方法,它将调用 Animal 类的 speak 方法。 ### 覆盖父类的方法 如果一个子类需要覆盖父类的方法,我们可以在子类中重新定义该方法。例如,在 Dog 类中,我们覆盖了 Animal 类的 speak 方法,使其输出“barks”而不是“makes a noise”。 ### 调用父类的方法 有时候,我们需要在子类中调用父类的方法。我们可以使用 super 关键字来调用父类的方法。例如,在 Dog 类中,我们可以通过调用 super.speak() 来调用 Animal 类的 speak 方法。 ### 总结 继承是一个非常常见的概念,也是面向对象编程中的重要概念之一。在 JavaScript 中,我们可以使用 extends 关键字来实现继承。通过继承,子类可以继承父类的属性和方法,也可以覆盖父类的方法,并且可以调用父类的方法。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值