类
类是一个面向对象的编程概念,在 JavaScript 中它类似于函数。类只是添加到 ES6 中的一个特殊函数。但是,它们通过为其分配属性来为您提供更多的功能和灵活性。
class MyClass {
…
}
构造 函数
表示类的特殊方法。它用于创建和初始化使用类创建的对象。
class MyClass {
constructor() {
this.myName = 'Sandy';
}
}
let myClass = new MyClass();
console.log(myClass.myName); // Sandy
构造函数还可以具有参数,用于在实例化时表示具有默认值的类。
class MyClass {
constructor(name) {
this.myName = name;
}
}
let myClass = new MyClass('Tanu');
console.log(myClass.myName); // Tanu
注意:您可以选择不为类声明构造函数。每个类声明都有一个默认构造函数
class MyClass {
…
}
MyClass 类具有默认构造函数,如下所示。
constructor() {
}
Getter 和 Setter
AKA 访问器方法,用于计算类的属性值。这些方法基本上分别以关键字和为前缀。
class MyClass {
constructor() {
this.myName = 'Sandy';
}
get name() {
return this.myName;
}
set name(newName) {
this.myName = newName;
}
}
let myClass = new MyClass();
console.log(myClass.name); // Sandy
myClass.name = 'Tanu';
console.log(myClass.name); // Tanu
你注意到了吗?这些方法可以在不使用括号的情况下调用,就像普通函数调用一样,这是因为在函数名称之前使用了 get 和 set 关键字。
班级吊装
提升是一种 JavaScript 机制,在代码执行之前,变量和函数声明会移动到其作用域的顶部。类声明不像 JavaScript 变量和函数那样被提升。让我们借助下面的示例来理解这一点。
JS中的功能提升:
getMyName(); // Sandy
function getMyName() {
console.log('Sandy');
}
如果您已经注意到,该函数在声明之前被调用。这不会因为 JavaScript 提升而给您带来错误。但是,如果您无法对 JavaScript 类做同样的事情。让我们看看下面的例子。
JS中的班级吊装:
new MyClass(); // ReferenceError
class MyClass { … }
由于 JavaScript 函数被提升,因此即使类在函数中实例化,也不会被提升。
function myFunction() {
new MyClass(); // ReferenceError
}
myFunction(); // ReferenceError
class MyClass {}
myFunction(); // OK
类表达式
与函数一样,类也可以用作表达式。有两种方法可以定义类:类声明和类表达式。到目前为止,我们学到的是一个类声明,现在让我们来探索一下类表达式。
let myClassLiteral = class MyClass {
name() {
return 'Hi, I am a Sandy';
}
}
let myClassInstance = new myClassLiteral();
console.log(myClassInstance.name()); // Hi, I am a Sandy
但是,如果您尝试创建 myClass 的实例,它将为您提供 ReferenceError。
let myClassInstance = new MyClass(); // ReferenceError: MyClass is not defined
因此,与函数表达式一样,类表达式可以是匿名的。
let myClass = class {
name() {
return 'Hi, I am a Sandy';
}
}
let myClassInstance = new myClass();
console.log(myClassInstance.name()); // Hi, I am a Sandy
注意:类表达式中的类名 (MyClass) 无关紧要,除非您尝试在类中使用它。是的,你没听错,我们可以访问其中的类名。
let myClassLiteral = class MyClass {
name() {
return MyClass.name;
}
}
let myClassInstance = new myClassLiteral();
console.log(myClassInstance.name()); // MyClass
子类(派生类)
一个类可以从其他类派生而来,带有 extends 子句。您需要做的就是从派生类中调用基类的构造函数(超级构造函数)。由于基类的构造函数是作为超级构造函数调用的,因此可以使用 super() 调用它。你做对了,super 代表你的基类,因此你不仅可以使用它来调用它的构造函数,还可以访问类的成员。如果不调用 super(),则无法派生类。是的,你没听错,它会给你一个错误。
class ParentClass {
constructor(name, surname) {
this.parentName = name;
this.surname = surname;
}
getParentName() {
return this.parentName + ' ' + this.surname;
}
}
class ChildClass extends ParentClass {
constructor(childName, parentName, surname) {
super(parentName, surname);
this.childName = childName;
}
getChildName() {
return this.childName + ' ' + super.getParentName(); // Reference line A
}
}
// Instantiate ChildClass
let child = new ChildClass('Sandip', 'Subhash', 'Salunke');
// Access properties of child and parent class
console.log(child.childName); // Sandip
console.log(child.parentName); // Subhash
console.log(child.surname); // Salunke
// Call member functions of child and parent class
console.log(child.getChildName()); // Sandip Subhash Salunke
console.log(child.getParentName()); // Subhash SalunkeI
请注意,如何使用 super 在上面的引用行 A 处调用基类成员函数。现在你可能会想,同样的事情也可以通过而不是 来完成。确实,我们也可以这样做,因为子类是从父类派生的,它可以直接访问其父类的函数。等等,但是如果子类具有同名的函数怎么办?这里有一个区别,我们必须使用 static 来调用父类的函数。
class ParentClass {
constructor(name, surname) {
this.parentName = name;
this.surname = surname;
}
getParentName() {
return this.parentName + ' ' + this.surname;
}
}
class ChildClass extends ParentClass {
constructor(childName, parentName, surname) {
super(parentName, surname);
this.childName = childName;
}
getParentName() {
return 'Sombody Salunke';
}
getChildName() {
return this.childName + ' ' + this.getParentName(); // Reference line A
}
}
let child = new ChildClass('Sandip', 'Subhash', 'Salunke');
console.log(child.getChildName()); // Sandip Sombody Salunke
注意:引用行 A,调用,这是子类的本地函数。因此返回的子名称为”this.getParentName()
child.getParentName()
Sandip Sombody Salunke
“而不是””。尝试更改并再次执行代码。太好了,看来你现在得到了正确的孩子名字。S<em>andip Subhash Salunke</em>
this.getParentName()
super.getParentName()
子类的原型是超类,这都是因为我们扩展了基类。原型的目的是通过向对象添加更多内容来扩展对象的行为,并在创建的所有实例中访问它们。
Object.getPrototypeOf(ChildClass) === ParentClass; // true
有趣的是,这仅适用于子类的近亲父级。如果从派生类派生类,则其原型将是超类,而不是超超类。
class GrandChildClass extends ChildClass {
// ...
}
Object.getPrototypeOf(GrandChildClass) === ChildClass; // true
Object.getPrototypeOf(GrandChildClass) === ParentClass; // false
我们可以扩展 JavaScript 的内置类,但不建议这样做。通常最好创建自己的类来控制其接口。
class Stack extends Array {
get topElement() {
return this[this.length - 1];
}
}
var stack = new Stack();
stack.push('world');
stack.push('hello');
console.log(stack.topElement); // hello
console.log(stack.length); // 2
Class 是 ECMAScript 标准,在 ES6 中添加。本教程中演示的大多数概念都是 ES6 功能,如 super、constructor、getter 和 setter、计算方法和属性名称等。
如果你觉得文章还不错,请大家 点赞、分享、留言 下,因为这将是我持续输出更多优质文章的最强动力!