前言
在 ECMAScript 2015(也称为 ES6)中,JavaScript 引入了类(class)的概念,使得 JavaScript 更加面向对象。而在 ECMAScript 2020 中,通过引入 Private Class Fields,可以在类中定义私有成员,进一步提高了类的封装性。
本文将介绍 Private Class Fields 的使用方法,包括如何定义和使用私有成员,以及与其他类成员的区别和注意事项。
定义私有成员
在 ES6 中,我们定义类成员可以使用 class 关键字,例如:
// www.javascriptcn.com code example
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
sayHello() {
console.log(`Hello, my name is ${this.name}, and I'm ${this.age} years old.`);
}
}在上面的例子中,name 和 age 是类的公有成员,可以在类的外部访问和修改。但是,有些成员可能希望只能在类的内部访问,这时就可以使用 Private Class Fields。
在类中定义 Private Class Fields 可以使用 # 符号,例如:
// www.javascriptcn.com code example
class Person {
#name;
#age;
constructor(name, age) {
this.#name = name;
this.#age = age;
}
sayHello() {
console.log(`Hello, my name is ${this.#name}, and I'm ${this.#age} years old.`);
}
}在上面的例子中,#name 和 #age 是类的私有成员,只能在类的内部访问和修改。注意,Private Class Fields 必须在类的其他成员之前定义。
使用私有成员
在类的内部,可以直接访问和修改 Private Class Fields。例如:
// www.javascriptcn.com code example
class Person {
#name;
#age;
constructor(name, age) {
this.#name = name;
this.#age = age;
}
sayHello() {
console.log(`Hello, my name is ${this.#name}, and I'm ${this.#age} years old.`);
}
changeName(newName) {
this.#name = newName;
}
}
const person = new Person('Alice', 20);
person.sayHello(); // 输出:Hello, my name is Alice, and I'm 20 years old.
person.changeName('Bob');
person.sayHello(); // 输出:Hello, my name is Bob, and I'm 20 years old.在类的外部,无法直接访问 Private Class Fields,会报错。例如:
// www.javascriptcn.com code example
class Person {
#name;
#age;
constructor(name, age) {
this.#name = name;
this.#age = age;
}
sayHello() {
console.log(`Hello, my name is ${this.#name}, and I'm ${this.#age} years old.`);
}
}
const person = new Person('Alice', 20);
console.log(person.#name); // 报错:SyntaxError: Private field '#name' must be declared in an enclosing class但是,可以通过类的公有方法来访问和修改 Private Class Fields。例如:
// www.javascriptcn.com code example
class Person {
#name;
#age;
constructor(name, age) {
this.#name = name;
this.#age = age;
}
sayHello() {
console.log(`Hello, my name is ${this.#name}, and I'm ${this.#age} years old.`);
}
changeName(newName) {
this.#name = newName;
}
getName() {
return this.#name;
}
}
const person = new Person('Alice', 20);
console.log(person.getName()); // 输出:Alice
person.changeName('Bob');
console.log(person.getName()); // 输出:Bob与其他类成员的区别
与公有成员不同,Private Class Fields 不能被继承。例如:
// www.javascriptcn.com code example
class Animal {
#name;
constructor(name) {
this.#name = name;
}
getName() {
return this.#name;
}
}
class Cat extends Animal {
#color;
constructor(name, color) {
super(name);
this.#color = color;
}
getColor() {
return this.#color;
}
}
const cat = new Cat('Tom', 'white');
console.log(cat.getName()); // 输出:Tom
console.log(cat.getColor()); // 输出:white
console.log(cat.#color); // 报错:SyntaxError: Private field '#color' must be declared in an enclosing class在上面的例子中,#name 是 Animal 类的私有成员,可以通过继承访问;而 #color 是 Cat 类的私有成员,无法通过继承访问。
另外,Private Class Fields 也不能被类的实例化对象访问。例如:
// www.javascriptcn.com code example
class Person {
#name;
constructor(name) {
this.#name = name;
}
getName() {
return this.#name;
}
}
const person = new Person('Alice');
console.log(person.#name); // 报错:SyntaxError: Private field '#name' must be declared in an enclosing class在上面的例子中,#name 是 Person 类的私有成员,无法通过实例化对象访问。
注意事项
在使用 Private Class Fields 时,需要注意以下几点:
- Private Class Fields 必须在类的其他成员之前定义;
- Private Class Fields 只能在类的内部访问和修改;
- Private Class Fields 不能被继承;
- Private Class Fields 不能被类的实例化对象访问;
- Private Class Fields 可以通过类的公有方法来访问和修改。
结语
Private Class Fields 是 ECMAScript 2020 中新增的一个特性,可以提高类的封装性,使得类的私有成员只能在类的内部访问和修改。在实际开发中,可以根据具体需求来选择使用 Private Class Fields 或公有成员,以达到更好的代码设计和封装性。
Source: FunTeaLearn,Please indicate the source for reprints https://funteas.com/post/67da57fca941bf713424771c