TypeScript에서 private 멤버의 구현을보고 있는데 약간 혼란 스럽습니다. Intellisense는 개인 멤버에 액세스하는 것을 허용하지 않지만 순수 JavaScript에서는 모든 것이 있습니다. 이것은 TS가 개인 구성원을 올바르게 구현하지 않는다고 생각합니다. 이견있는 사람?
class Test{
private member: any = "private member";
}
alert(new Test().member);
TypeScript에서 private 멤버의 구현을보고 있는데 약간 혼란 스럽습니다. Intellisense는 개인 멤버에 액세스하는 것을 허용하지 않지만 순수 JavaScript에서는 모든 것이 있습니다. 이것은 TS가 개인 구성원을 올바르게 구현하지 않는다고 생각합니다. 이견있는 사람?
class Test{
private member: any = "private member";
}
alert(new Test().member);
답변:
유형 검사와 마찬가지로 멤버의 개인 정보는 컴파일러 내에서만 적용됩니다.
개인 속성은 일반 속성으로 구현되며 클래스 외부의 코드는 액세스 할 수 없습니다.
클래스 내에서 진정으로 비공개로 만들려면 클래스의 멤버가 될 수 없으며 객체를 생성하는 코드 내 함수 범위 내에 생성 된 지역 변수가됩니다. 즉, 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키워드 로 표시된 필드와 다른 것입니다.
Ref. https://devblogs.microsoft.com/typescript/announcing-typescript-3-8-beta/
이 문제에 대한 공식 토론 링크에 대한 Sean Feldman에게 감사드립니다. 링크에 대한 그의 답변 을 참조하십시오 .
그가 링크 한 토론을 읽었으며 여기에 주요 요점에 대한 요약이 있습니다.
this일종의 해결 방법 없이는 액세스 할 수 없습니다.@private이 메서드 이름을 효과적으로 축소 할 수 있음을 인식하는 축소자를 사용하여 비공개 메서드에 주석을 추가 합니다.
내 보낸 코드에서 가시성 지원 추가에 대한 전반적인 반론 :
TypeScript에서 Private 함수는 클래스 내에서만 액세스 할 수 있습니다. 처럼
그리고 비공개 회원에 접근을 시도하면 오류가 표시됩니다. 다음은 그 예입니다.
참고 : 자바 스크립트에서는 문제가 없으며 두 기능 모두 외부에서 액세스 할 수 있습니다.
나는 이것이 오래된 논의라는 것을 알고 있지만 컴파일 된 JavaScript 클래스의 공용 인터페이스로 "누출"되는 TypeScript의 개인 변수 및 메서드 문제에 대한 내 솔루션을 공유하는 것이 여전히 유용 할 수 있습니다.
나에게이 문제는 순전히 외형적인 문제입니다. 즉, 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하지 않습니다.