在 ES6 中,引入了 class 的概念,使得面向对象编程更加容易。而在 ES12 中,又新增了一些特性,如 private 字段、static 方法等,使得 class 的功能更加完善。然而,在使用这些特性时,我们也会遇到一些坑点。本文将介绍这些坑点,并提供解决方案。
坑点一:private 字段的访问限制
ES12 中新增了 private 字段,可以在 class 中定义只能在内部访问的字段。例如:
// javascriptcn.com 代码示例 class Person { #name; constructor(name) { this.#name = name; } getName() { return this.#name; } } const person = new Person('Alice'); console.log(person.#name); // SyntaxError console.log(person.getName()); // Alice
在上面的代码中,#name
是一个 private 字段,只能在 class 内部访问。而在外部访问时,会抛出 SyntaxError。
然而,如果我们将 class 定义在一个模块中,并将其导出,那么在另一个模块中也无法访问 private 字段,即使是同一个文件。例如:
// javascriptcn.com 代码示例 // person.js export class Person { #name; constructor(name) { this.#name = name; } getName() { return this.#name; } } // main.js import { Person } from './person.js'; const person = new Person('Alice'); console.log(person.#name); // SyntaxError console.log(person.getName()); // Alice
这是因为 private 字段的访问限制是在编译时确定的,而不是在运行时。因此,如果要在同一个文件中访问 private 字段,可以使用 WeakMap。例如:
// javascriptcn.com 代码示例 const nameMap = new WeakMap(); export class Person { constructor(name) { nameMap.set(this, name); } getName() { return nameMap.get(this); } }
在上面的代码中,我们使用了一个 WeakMap,将对象和其 private 字段对应起来。这样,在另一个方法中访问 private 字段时,只需要使用 WeakMap.get() 方法即可。
坑点二:static 方法中的 this
在 class 中定义 static 方法时,需要注意其中的 this 指向。例如:
// javascriptcn.com 代码示例 class Person { static name = 'Person'; static getName() { return this.name; } } class Student extends Person { static name = 'Student'; } console.log(Person.getName()); // Person console.log(Student.getName()); // Student
在上面的代码中,我们定义了一个静态方法 getName(),返回一个静态字段 name。在子类中,我们覆盖了 name 字段。然而,当我们调用 Student.getName() 时,返回的却是 Person,而不是 Student。这是因为在 static 方法中,this 指向的是 class,而不是实例。因此,我们需要使用类名来访问静态字段。例如:
// javascriptcn.com 代码示例 class Person { static name = 'Person'; static getName() { return Person.name; } } class Student extends Person { static name = 'Student'; } console.log(Person.getName()); // Person console.log(Student.getName()); // Student
坑点三:private 字段的继承
在 ES12 中,继承类时,private 字段的访问限制也会被继承。例如:
// javascriptcn.com 代码示例 class Person { #name; constructor(name) { this.#name = name; } getName() { return this.#name; } } class Student extends Person { #grade; constructor(name, grade) { super(name); this.#grade = grade; } getGrade() { return this.#grade; } } const student = new Student('Alice', 'A'); console.log(student.getName()); // Alice console.log(student.getGrade()); // A console.log(student.#name); // SyntaxError console.log(student.#grade); // SyntaxError
在上面的代码中,我们定义了一个私有字段 #name,在子类中也定义了一个私有字段 #grade。然而,在子类中,我们无法访问父类的私有字段 #name。这是因为在继承时,子类并没有继承父类的私有字段,而是定义了一个新的私有字段。因此,如果要在子类中访问父类的私有字段,可以使用 super 关键字。例如:
// javascriptcn.com 代码示例 class Person { #name; constructor(name) { this.#name = name; } getName() { return this.#name; } } class Student extends Person { #grade; constructor(name, grade) { super(name); this.#grade = grade; } getGrade() { return this.#grade; } getName() { return super.getName(); } } const student = new Student('Alice', 'A'); console.log(student.getName()); // Alice console.log(student.getGrade()); // A console.log(student.#name); // SyntaxError console.log(student.#grade); // SyntaxError
在上面的代码中,我们在子类中重写了 getName() 方法,并使用 super.getName() 来访问父类的私有字段。
总结
在 ES12 中,class 的功能更加完善,但也带来了一些坑点。在使用 private 字段时,需要注意其访问限制,以及在继承时的表现。在使用 static 方法时,需要注意其中的 this 指向。通过本文的介绍,相信读者已经掌握了解决这些坑点的方法,可以更加顺利地使用 ES12 中的 class。
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/6567f778d2f5e1655d0c370c