在TypeScript 3.8+中,使用private
关键字将成员标记为私有之间有什么区别:
class PrivateKeywordClass {
private value = 1;
}
并使用为JavaScript建议的#
私有字段:
class PrivateFieldClass {
#value = 1;
}
我应该优先选择另一个吗?
TypeScript中的private关键字是编译时注释。它告诉编译器,一个属性只能在该类内部访问:
class PrivateKeywordClass {
private value = 1;
}
const obj = new PrivateKeywordClass();
obj.value // compiler error: Property 'value' is private and only accessible within class 'PrivateKeywordClass'.
但是,可以很容易地跳过编译时检查,例如,通过舍弃类型信息:
const obj = new PrivateKeywordClass();
(obj as any).value // no compile error
private
在运行时也不强制使用关键字
将TypeScript编译为JavaScript时,private
只需删除关键字:
class PrivateKeywordClass {
private value = 1;
}
成为:
class PrivateKeywordClass {
constructor() {
this.value = 1;
}
}
由此,您可以看到为什么private
关键字不提供任何运行时保护的原因:在生成的JavaScript中,它只是普通的JavaScript属性。
私有字段可确保属性在运行时保持私有状态:
class PrivateFieldClass {
#value = 1;
getValue() { return this.#value; }
}
const obj = new PrivateFieldClass();
// You can't access '#value' outside of class like this
obj.value === undefined // This is not the field you are looking for.
obj.getValue() === 1 // But the class itself can access the private field!
// Meanwhile, using a private field outside a class is a runtime syntax error:
obj.#value
// While trying to access the private fields of another class is
// a runtime type error:
class Other {
#value;
getValue(obj) {
return obj.#value // TypeError: Read of private field #value from an object which did not contain the field
}
}
new Other().getValue(new PrivateKeywordClass());
如果尝试在类外使用私有字段,TypeScript还将输出编译时错误:
专用字段来自JavaScript提案,也可以在常规JavaScript中使用。
如果您在TypeScript中使用私有字段,并且将JavaScript的较旧版本定位为您的输出(例如es6
或)es2018
,则TypeScript将尝试生成模拟私有字段运行时行为的代码。
class PrivateFieldClass {
constructor() {
_x.set(this, 1);
}
}
_x = new WeakMap();
如果您定位esnext
,TypeScript将发出私有字段:
class PrivateFieldClass {
constructor() {
this.#x = 1;
}
#x;
}
这取决于您要实现的目标。
该private
关键字是一个很好的默认值。它完成了设计要完成的任务,并已被TypeScript开发人员成功使用多年。而且,如果您已有代码库,则无需切换所有代码即可使用私有字段。如果您未定位目标esnext
,则尤其如此,因为TS为私有字段发出的JS可能会对性能产生影响。另外请记住,私有字段与private
关键字还有其他细微但重要的区别
但是,如果您需要实施运行时私有性或输出esnext
JavaScript,则应使用私有字段。
还请记住,随着私有字段在JavaScript / TypeScript生态系统中变得更加广泛,有关使用一种或另一种的组织/社区约定也将不断发展。
私有字段不会由Object.getOwnPropertyNames
和类似方法返回
私有字段不由序列化 JSON.stringify
在继承方面有一些重要的案例。
例如,TypeScript禁止在子类中声明与超类中的私有属性同名的私有属性。
class Base {
private value = 1;
}
class Sub extends Base {
private value = 2; // Compile error:
}
对于私有字段,情况并非如此:
class Base {
#value = 1;
}
class Sub extends Base {
#value = 2; // Not an error
}
一个private
没有初始化的关键字私有财产不会产生在发出JavaScript中的财产申报:
class PrivateKeywordClass {
private value?: string;
getValue() { return this.value; }
}
编译为:
class PrivateKeywordClass {
getValue() { return this.value; }
}
私有字段总是生成属性声明:
class PrivateKeywordClass {
#value?: string;
getValue() { return this.#value; }
}
编译为(定位时esnext
):
class PrivateKeywordClass {
#value;
getValue() { return this.#value; }
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句