在 ECMAScript 2020 标准中,类继承模式得到了进一步的改进,其中 super 关键字的妙用是其中一个重要的特性。本文将详细介绍 super 关键字的用法,并提供相关的示例代码,以帮助读者更好地理解和应用这一特性。
super 关键字的基本用法
在 JavaScript 中,我们可以通过 extends 关键字来实现类的继承。当子类需要调用父类的方法或属性时,我们可以使用 super 关键字。super 关键字可以用在两个地方:
- 在子类的构造函数中,用于调用父类的构造函数。
- 在子类的普通方法中,用于调用父类的同名方法。
下面是一个简单的示例代码:
// javascriptcn.com 代码示例 class Animal { constructor(name) { this.name = name; } speak() { console.log(`${this.name} makes a noise.`); } } class Dog extends Animal { constructor(name) { super(name); } speak() { super.speak(); console.log(`${this.name} barks.`); } } const d = new Dog('Mitzie'); d.speak();
在上面的代码中,我们定义了一个 Animal 类和一个 Dog 类,Dog 类继承自 Animal 类。在 Dog 类的构造函数中,我们通过 super(name) 调用了父类 Animal 的构造函数,并将 name 参数传递给了父类的构造函数。在 Dog 类的 speak 方法中,我们通过 super.speak() 调用了父类 Animal 的 speak 方法,并在后面输出了狗叫的声音。最后,我们创建了一个名为 Mitzie 的 Dog 实例,并调用了它的 speak 方法。
运行上面的代码,我们可以得到以下输出:
Mitzie makes a noise. Mitzie barks.
从输出结果中可以看出,Dog 类成功地调用了父类 Animal 的方法,并且在其基础上添加了自己的逻辑。
super 关键字的高级用法
除了基本用法之外,super 关键字还有一些高级用法,可以进一步提高代码的可读性和可维护性。
super() 和 this 的顺序
在子类的构造函数中,我们必须先调用 super() 方法才能使用 this 关键字。这是因为在 JavaScript 中,子类没有自己的 this 对象,它继承了父类的 this 对象。因此,如果我们在调用 super() 方法之前使用 this 关键字,就会抛出一个引用错误。
下面是一个示例代码,演示了 super() 和 this 关键字的顺序问题:
// javascriptcn.com 代码示例 class Animal { constructor(name) { this.name = name; console.log(`Animal name is ${this.name}.`); } } class Dog extends Animal { constructor(name) { console.log(`Dog name is ${name}.`); this.age = 2; super(name); } } const d = new Dog('Mitzie');
在上面的代码中,我们定义了一个 Animal 类和一个 Dog 类,Dog 类继承自 Animal 类。在 Dog 类的构造函数中,我们先输出了狗的名字,然后给狗设置了一个年龄属性 age,并调用了父类 Animal 的构造函数。最后,我们创建了一个名为 Mitzie 的 Dog 实例。
运行上面的代码,我们会发现会抛出一个引用错误,提示 this 关键字在调用 super() 方法之前使用了:
Dog name is Mitzie. ReferenceError: Must call super constructor in derived class before accessing 'this' or returning from derived constructor
这是因为我们在调用 super() 方法之前使用了 this 关键字,导致程序出错。为了解决这个问题,我们需要将 super() 方法调用放在 this 关键字之前,如下所示:
// javascriptcn.com 代码示例 class Animal { constructor(name) { this.name = name; console.log(`Animal name is ${this.name}.`); } } class Dog extends Animal { constructor(name) { super(name); console.log(`Dog name is ${name}.`); this.age = 2; } } const d = new Dog('Mitzie');
在上面的代码中,我们先调用了父类 Animal 的构造函数,然后才使用了 this 关键字。这样,程序就可以正常运行了。
super 关键字的属性访问器
在 JavaScript 中,我们可以使用属性访问器来访问对象的属性。属性访问器包括 getter 和 setter 两种类型。在子类中,我们可以通过 super 关键字来访问父类的属性访问器,从而实现属性的继承和重写。
下面是一个示例代码,演示了如何在子类中继承和重写父类的属性访问器:
// javascriptcn.com 代码示例 class Animal { constructor(name) { this._name = name; } get name() { return this._name; } set name(value) { this._name = value; } } class Dog extends Animal { constructor(name) { super(name); } get name() { return `Dog ${super.name}`; } set name(value) { super.name = value; } } const d = new Dog('Mitzie'); console.log(d.name); // 输出 "Dog Mitzie" d.name = 'Buddy'; console.log(d.name); // 输出 "Dog Buddy"
在上面的代码中,我们定义了一个 Animal 类和一个 Dog 类,Dog 类继承自 Animal 类。在 Animal 类中,我们定义了一个名为 _name 的私有属性,并通过 get 和 set 方法实现了对该属性的访问。在 Dog 类中,我们通过 get 和 set 方法重写了父类的属性访问器,并通过 super 关键字访问了父类的 name 属性。最后,我们创建了一个名为 Mitzie 的 Dog 实例,并输出了它的名字。然后,我们将它的名字改为 Buddy,并再次输出了它的名字。
从输出结果中可以看出,Dog 类成功地继承了父类 Animal 的属性访问器,并在此基础上添加了自己的逻辑。
总结
在 ECMAScript 2020 中,super 关键字的妙用为类继承模式带来了更加灵活和可读性的代码风格。通过本文的介绍和示例代码,读者可以更好地理解和掌握 super 关键字的用法,并在实际开发中灵活应用,提高代码的质量和可维护性。
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/6561d5a8d2f5e1655dbe2579