TS Private Fields

官网说明

Handbook - TypeScript 3.8

概述

私有字段的支持是从 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.
    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.
    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));

私有字段的尝试

在看过对私有字段的概述及用法介绍后,我实际尝试了一番,但却碰到了一些问题,具体如下:

  • 示例代码:

    // private-field.ts
    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();
    

    以上示例代码完全是从官网 Copy 下来的,但是在 IDE 中却显示出错!
    不支持

    这是怎么回事呢?

  • 看一下报错信息:

    // TS18028: Private identifiers are only available when targeting ECMAScript 2015 and higher.
    // Private 标识符仅在 ECMAScript 2015 及更高版本可用
    

    原来如此!我当前的版本不支持私有字段!

    但是不对啊,我的 TypeScript 版本就是 3.8 啊!
    TypeScript version

    那是怎么回事呢?在 stackoverflow 的一个提问中我找到了原因:我的 tsconfig.json 配置错了
    错误target

    我的编译目标版本错了,是 es5 ,而报错信息已经明确提示了,要求的版本是 ES 2015 及以上

  • 解决方案

    找到了问题所在,那么,解决起来就很简单了!
    target

    可以看到,在将编译目标版本改到 es2015 后,原本 private-field.ts 上的出错提示已经消失了。

  • 运行效果
    运行效果

  • 私有字段的效果

    示例已经顺利运行起来了,那么,到底这个私有字段有没有用呢?

    在之前的示例代码中加上一行:

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

私有字段的支持

由于目前 ECMAScript 对私有字段的支持尚在 stage-3 ,虽然可以用 Babel 实现在 JavaScript 中使用私有字段,但是不使用插件的话,将 TypeScript 编译为 JavaScript 会报错。

当然,也有可能是可以编译成功的,但是我目前由于没有深入地研究,所以暂时还没有实验成功。
编译成功

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

十甫寸木南

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值