本文主要是介绍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() 时确保传递所有必需的参数。
如果无法修改父类或者确实不想在子类中使用父类的初始化逻辑,那么可能需要重新考虑是否应该使用继承,或者寻找其他设计模式(例如组合)来满足需求了。
这篇关于js中类的继承--extends的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!