我正在研究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);
Answers:
就像类型检查一样,成员的隐私仅在编译器中强制执行。
私有属性被实现为常规属性,并且不允许类外的代码对其进行访问。
为了使某些东西真正成为类内的私有对象,它不能成为该类的成员,而应是在创建对象的代码内的函数作用域内创建的局部变量。这意味着您不能像类的成员那样访问它,即使用this关键字。
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无关),仅应在绝对必要的情况下使用。
var _this在作用域函数中使用来做到这一点吗?为什么在类范围内会有疑虑呢?
一旦对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)();
}
}
}
protected参数支持如何?:D
由于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/announcing-typescript-3-8-beta/
感谢Sean Feldman提供了有关此问题的正式讨论的链接- 链接请参阅他的答案。
我阅读了他链接的讨论,这是关键点的摘要:
this某种解决方法,它们将无法访问@private使注释器识别私有方法可以有效地缩小方法名称的注释器来
注释私有方法在发出的代码中增加可见性支持的总体反论点:
我意识到这是一个较旧的讨论,但是在TypeScript中“泄漏”到已编译的JavaScript类的公共接口中时,解决我的私有变量和方法的问题可能仍然有用。
对我来说,这个问题纯粹是表面上的问题,即与在DevTools中查看实例变量时的视觉混乱有关。我的解决方法是将私有声明分组到另一个类中,然后在主类中实例化该类,然后将其分配给一个private(但仍在JS中公开可见)名称为__(双下划线)的变量。
例:
class Privates {
readonly DEFAULT_MULTIPLIER = 2;
foo: number;
bar: number;
someMethod = (multiplier: number = this.DEFAULT_MULTIPLIER) => {
return multiplier * (this.foo + this.bar);
}
private _class: MyClass;
constructor(_class: MyClass) {
this._class = _class;
}
}
export class MyClass {
private __: Privates = new Privates(this);
constructor(foo: number, bar: number, baz: number) {
// assign private property values...
this.__.foo = foo;
this.__.bar = bar;
// assign public property values...
this.baz = baz;
}
baz: number;
print = () => {
console.log(`foo=${this.__.foo}, bar=${this.__.bar}`);
console.log(`someMethod returns ${this.__.someMethod()}`);
}
}
let myClass = new MyClass(1, 2, 3);
当myClass在DevTools中查看该实例时,您没有看到它们的所有“私有”成员与真正的公共成员混合在一起(在正确重构的现实生活代码中,它们在视觉上会非常混乱),您会看到它们整齐地分组在折叠后的__属性中:
这是添加适当的私有属性的可重用方法:
/**
* Implements proper private properties.
*/
export class Private<K extends object, V> {
private propMap = new WeakMap<K, V>();
get(obj: K): V {
return this.propMap.get(obj)!;
}
set(obj: K, val: V) {
this.propMap.set(obj, val);
}
}
假设您在Client某个地方需要两个私有属性的类:
prop1: stringprop2: number下面是您的实现方式:
// our private properties:
interface ClientPrivate {
prop1: string;
prop2: number;
}
// private properties for all Client instances:
const pp = new Private<Client, ClientPrivate>();
class Client {
constructor() {
pp.set(this, {
prop1: 'hello',
prop2: 123
});
}
someMethod() {
const privateProps = pp.get(this);
const prop1 = privateProps.prop1;
const prop2 = privateProps.prop2;
}
}
而且,如果您只需要一个私有属性,那么它将变得更加简单,因为ClientPrivate在这种情况下您无需定义任何私有属性。
值得注意的是,在大多数情况下,类Private仅提供一个可读性很好的签名,而直接使用WeakMap则不能。