Javascript 클래스를 만들고 있으며 Java와 같은 공용 정적 필드를 갖고 싶습니다. 다음은 관련 코드입니다.
export default class Agent {
CIRCLE: 1,
SQUARE: 2,
...
이것은 내가 얻는 오류입니다.
line 2, col 11, Class properties must be methods. Expected '(' but instead saw ':'.
ES6 모듈이 이것을 허용하지 않는 것 같습니다. 원하는 동작을 얻을 수있는 방법이 있습니까? 아니면 getter를 작성해야합니까?
답변
접근 자와 “정적”키워드를 사용하여 “공개 정적 필드”를 만듭니다.
class Agent {
static get CIRCLE() {
return 1;
}
static get SQUARE() {
return 2;
}
}
Agent.CIRCLE; // 1
사양을 보면 14.5 — 클래스 정의 — 의심스럽게 관련된 것을 볼 수 있습니다. 🙂
ClassElement [Yield] :
MethodDefinition [? Yield]
static MethodDefinition [? Yield];
그래서 거기에서 14.5.14 — Runtime Semantics : ClassDefinitionEvaluation —을 따라 가면 그것이 실제로하는 것처럼 보이는지 다시 확인할 수 있습니다. 특히 20 단계 :
- 메서드에서 순서대로 각 ClassElement m에 대해
- 경우 m의 IsStatic은 false입니다 다음,
- 상태를 proto 및 false 인수를 사용하여 m에 대해 PropertyDefinitionEvaluation을 수행 한 결과라고합시다.
- 그밖에,
- status를 인수 F 및 false로 m에 대해 PropertyDefinitionEvaluation을 수행 한 결과라고합시다.
- 상태가 갑작스런 완료 인 경우
- 실행중인 실행 컨텍스트의 LexicalEnvironment를 lex로 설정합니다.
- 반환 상태.
IsStatic은 14.5.9 이전에 정의되었습니다.
ClassElement : static MethodDefinition
true 를 반환합니다.
따라서 PropertyMethodDefinition
“F”(생성자, 함수 객체)를 인수로 사용하여 호출되며, 그러면 해당 객체에 대한 접근 자 메서드 가 생성 됩니다.
이것은 이미 적어도 IETP (기술 미리보기), 6to5 및 Traceur 컴파일러에서 작동합니다.
답변
이 문제를 해결하기 위해 Daniel Ehrenberg와 Jeff Morrison이 작성한 “Static Class Features” 라는 3 단계 ECMAScript 제안 이 있습니다. 3 단계 “클래스 필드” 제안 과 함께 향후 코드는 다음과 같습니다.
class MyClass {
static myStaticProp = 42;
myProp = 42;
myProp2 = this.myProp;
myBoundFunc = () => { console.log(this.myProp); };
constructor() {
console.log(MyClass.myStaticProp); // Prints '42'
console.log(this.myProp); // Prints '42'
this.myBoundFunc(); // Prints '42'
}
}
위의 내용은 다음과 같습니다.
class MyClass {
constructor() {
this.myProp = 42;
this.myProp2 = this.myProp;
this.myBoundFunc = () => { console.log(this.myProp); };
console.log(MyClass.myStaticProp); // Prints '42'
console.log(this.myProp); // Prints '42'
this.myBoundFunc(); // Prints '42'
}
}
MyClass.myStaticProp = 42;
Babel 은 @ babel / plugin-proposal-class-properties ( 3 단계 사전 설정에 포함)를 통해 클래스 필드 트랜스 파일을 지원 하므로 JavaScript 런타임에서 지원하지 않는 경우에도이 기능을 사용할 수 있습니다.
@kangax의 getter 선언 솔루션과 비교할 때이 솔루션은 함수를 호출하는 대신 직접 속성에 액세스하기 때문에 더 성능이 좋습니다.
이 제안이 받아 들여지면 자바 및 C♯와 같은 전통적인 객체 지향 언어와 유사한 방식으로 자바 스크립트 코드를 작성할 수 있습니다.
편집 : 통합 된 클래스 필드 제안이 이제 3 단계에 있습니다. Babel v7.x 패키지로 업데이트합니다.
편집 (2020 년 2 월) : 정적 클래스 기능이 다른 제안으로 분할되었습니다. 감사합니다 @ GOTO0!
답변
현재 ECMAScript 6 초안 (2015 년 2 월 현재)에서 모든 클래스 속성은 값이 아니라 메서드 여야합니다 (ECMAScript에서 “속성”은 개념 상 OOP 필드와 유사하지만 필드 값은 Function
객체 여야하며 a Number
또는 Object
) 와 같은 다른 값 .
기존 ECMAScript 생성자 속성 지정자를 사용하여 계속 지정할 수 있습니다.
class Agent {
}
Agent.CIRCLE = 1;
Agent.SQUARE = 2;
...
답변
정적 변수를 최대한 활용하기 위해이 접근 방식을 따랐습니다. 좀 더 구체적으로 말하자면, 개인 변수를 사용하거나 공용 getter 만 있거나 getter 또는 setter를 모두 갖는 데 사용할 수 있습니다. 마지막 경우에는 위에 게시 된 솔루션 중 하나와 동일합니다.
var Url = (() => {
let _staticMember = [];
return class {
static getQueries(hash = document.location.hash) {
return hash;
}
static get staticMember(){
return _staticMember;
}
};
})();
Usages:
console.log(Url.staticMember); // [];
Url.staticMember.push('it works');
console.log(Url.staticMember); // ['it works'];
Url을 확장하는 다른 클래스를 만들 수 있었고 작동했습니다.
바벨을 사용하여 ES6 코드를 ES5로 변환했습니다.
답변
@kangax의 대답은 기존 OOP 언어의 전체 정적 동작을 모방하지 않습니다. const agent = new Agent; agent.CIRCLE; // Undefined
OOP와 같은 정적 속성에 액세스하려면 다음은 내 솔루션입니다.
class NewApp {
get MULTIPLE_VERSIONS_SUPPORTED() {
return this.constructor.MULTIPLE_VERSIONS_SUPPORTED; // Late binding for inheritance
}
}
NewApp.MULTIPLE_VERSIONS_SUPPORTED = true;
다음과 같이 코드를 테스트하십시오.
class NewApp {
get MULTIPLE_VERSIONS_SUPPORTED() {
console.log('this.constructor.name:', this.constructor.name); // late binding
return this.constructor.MULTIPLE_VERSIONS_SUPPORTED;
}
}
// Static property can be accessed by class
NewApp.MULTIPLE_VERSIONS_SUPPORTED = true;
const newApp = new NewApp;
// Static property can be accessed by it's instances
console.log('newApp.MULTIPLE_VERSIONS_SUPPORTED:', newApp.MULTIPLE_VERSIONS_SUPPORTED); // true
// Inheritance
class StandardApp extends NewApp {}
// Static property can be inherited
console.log('StandardApp.MULTIPLE_VERSIONS_SUPPORTED:', StandardApp.MULTIPLE_VERSIONS_SUPPORTED); // true
// Static property can be overwritten
StandardApp.MULTIPLE_VERSIONS_SUPPORTED = false;
const std = new StandardApp;
console.log('std.MULTIPLE_VERSIONS_SUPPORTED:', std.MULTIPLE_VERSIONS_SUPPORTED); // false