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 也会存在。

posted on 2024-07-03 22:56  梁飞宇  阅读(213)  评论(0)    收藏  举报