我正在研究 TypeScript 中私有成员的实现,我发现它有点令人困惑。Intellisense 不允许访问私有成员,但在纯 JavaScript 中,一切都在那里。这让我认为 TS 没有正确实现私有成员。有什么想法吗?
class Test{
private member: any = "private member";
}
alert(new Test().member);
我正在研究 TypeScript 中私有成员的实现,我发现它有点令人困惑。Intellisense 不允许访问私有成员,但在纯 JavaScript 中,一切都在那里。这让我认为 TS 没有正确实现私有成员。有什么想法吗?
class Test{
private member: any = "private member";
}
alert(new Test().member);
与类型检查一样,成员的隐私仅在编译器中强制执行。
私有属性实现为常规属性,不允许类外的代码访问它。
为了使类内部的某些东西真正私有,它不能是类的成员,它是在创建对象的代码内的函数作用域内创建的局部变量。这意味着您不能像类的成员那样访问它,即使用this
关键字。
JavaScript 确实支持私有变量。
function MyClass() {
var myPrivateVar = 3;
this.doSomething = function() {
return myPrivateVar++;
}
}
在 TypeScript 中,这可以这样表达:
class MyClass {
doSomething: () => number;
constructor() {
var myPrivateVar = 3;
this.doSomething = function () {
return myPrivateVar++;
}
}
}
编辑
这种方法只能用于少量的地方是绝对必要的。例如,如果您需要临时缓存密码。
使用这种模式会产生性能成本(与 Javascript 或 Typescript 无关),只能在绝对必要的情况下使用。
由于 TypeScript 3.8 将发布,您将能够声明在包含类之外无法访问甚至无法检测到的私有字段 。
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.
私有字段以#
字符开头
请注意,这些私有字段将与用private
关键字标记的字段不同
参考 https://devblogs.microsoft.com/typescript/annoucing-typescript-3-8-beta/
一旦对WeakMap 的支持更加广泛,这里的示例 #3 中详细介绍了一种有趣的技术。
它允许私有数据并通过允许从原型方法而不是仅实例方法访问数据来避免 Jason Evans 示例的性能成本。
链接的 MDN WeakMap 页面列出了 Chrome 36、Firefox 6.0、IE 11、Opera 23 和 Safari 7.1 的浏览器支持。
let _counter = new WeakMap();
let _action = new WeakMap();
class Countdown {
constructor(counter, action) {
_counter.set(this, counter);
_action.set(this, action);
}
decrement() {
let counter = _counter.get(this);
if (counter < 1) return;
counter--;
_counter.set(this, counter);
if (counter === 0) {
_action.get(this)();
}
}
}
感谢 Sean Feldman 提供有关此问题的官方讨论的链接 - 请参阅他对链接的回答。
我阅读了他链接到的讨论,以下是要点摘要:
this
某种解决方法,它们将无法访问@private
识别注释可以有效地缩小方法名称的缩小器对私有方法进行注释
在发出的代码中添加可见性支持的总体反驳: