TypeScript细碎知识点:私有字段和 private 修饰符
一,概述
对私有字段的支持是从 TypeScript 3.8 开始的。(私有字段目前在 EcmaScript 中尚处于 stage-3 )
私有字段以 # 开始,如下:
class Person { //私有属性 #name: string //构造函数 constructor(name: string) { this.#name = name; } //实例方法 greet() { console.log(`Hello, my name is ${this.#name}!`); } } let jeremy = new Person("Jeremy Bearimy"); jeremy.#name // ~~~~~ // Property '#name' is not accessible outside class 'Person' // because it has a private identifier.
二,私有字段的用法
私有字段的使用规则:
- 私有字段以 # 开始。
- 每个私有字段的名字,在被包含的类中,都是唯一的。
- TypeScript 辅助功能修饰符(public、private 等)不能在私有字段上使用。
- 私有字段不能在所包含的类之外访问;即使是对于 JavaScript 使用者来说也是如此。
针对以上规则的第 2 条 “每个私有字段的名字,在被包含的类中,都是唯一的。”,有以下示例对其做出解释:
⏰ 常规属性声明容易在子类中被改写,私有字段不会被子类改写,每个私有字段,在所包含的类中,都是唯一的。
常规属性声明
class C { foo = 10; cHelper() { return this.foo; } } class D extends C { foo = 20; dHelper() { return this.foo; } } let instance = new D(); // 'this.foo' refers to the same property on each instance. // “this.foo '在每个实例上引用相同的属性。 console.log(instance.cHelper()); // prints '20' console.log(instance.dHelper()); // prints '20'
私有字段声明
class C { #foo = 10; cHelper() { return this.#foo; } } class D extends C { #foo = 20; dHelper() { return this.#foo; } } let instance = new D(); // 'this.#foo' refers to a different field within each class. // 'this.#foo' 引用每个类中的不同字段。 console.log(instance.cHelper()); // prints '10' console.log(instance.dHelper()); // prints '20'
⏰ 对于私有字段的使用,还需要注意的一点是:除非在某个对象的类型声明中声明了某个私有字段,否则,在未声明该私有字段的对象中无法使用该私有字段,会报错。
class Square { #sideLength: number; constructor(sideLength: number) { this.#sideLength = sideLength; } equals(other: any) { return this.#sideLength === other.#sideLength; } } const a = new Square(100); const b = { sideLength: 100 }; // Boom! // TypeError: attempted to get private field on non-instance // This fails because 'b' is not an instance of 'Square'. console.log(a.equals(b));
三,私有字段的尝试
class Person { #name: string; constructor(name: string) { this.#name = name; } greet() { console.log(`Hello, my name is ${this.#name}!`); } } const jeremy = new Person("Jeremy Bearimy"); jeremy.greet(); console.log(jeremy.#name); // ~~~~~ // TS18013: Property '#name' is not accessible outside class 'Person' because it has a private identifier.
报错了!
四,私有字段和 private 修饰符的区别
-
TypeScript 中的 private 修饰符在编译为 JavaScript 后就完全被删掉了,相当于实际上是没有用的。
- 私有字段即便编译为 JavaScript 也会存在。
浙公网安备 33010602011771号