ES6 클래스 인스턴스에서 클래스 이름을 얻는 ‘조화로운’방법이 있습니까? 이것 말고도
someClassInstance.constructor.name
현재 나는 Traceur 구현에 의존하고 있습니다. 그리고 Function.name
트레이서 (Traceur)는 그렇지 않은 동안 바벨 (Babel)은 폴리 필을 가지고있는 것 같습니다 .
요약하면 ES6 / ES2015 / Harmony에는 다른 방법이 없었으며 ES에서는 ATM이 예상되지 않습니다.
서버 측 응용 프로그램에는 유용한 패턴을 제공 할 수 있지만 브라우저 / 데스크톱 / 모바일 용 응용 프로그램에서는 필요하지 않습니다.
Babel 은core-js
polyfill에 사용하므로Function.name
Traceur 및 TypeScript 응용 프로그램에 적합하게 수동으로로드해야합니다.
답변
someClassInstance.constructor.name
이 작업을 수행하는 올바른 방법입니다. 트랜스 파일러는이를 지원하지 않을 수 있지만 사양에 따라 표준 방식입니다. ( name
ClassDeclaration 프로덕션을 통해 선언 된 함수 의 특성은 6 단계 14.5.15 에서 설정됩니다 .)
답변
@Domenic이 말했듯이을 사용하십시오 someClassInstance.constructor.name
. @Esteban은 주석에서 언급합니다.
someClassInstance.constructor
함수입니다. 모든 함수에는name
속성이 있습니다 …
따라서 클래스 이름을 정적으로 액세스하려면 다음을 수행하십시오 (이것은 내 Babel 버전 BTW에서 작동합니다. @Domenic에 대한 의견에 따르면 마일리지가 다를 수 있습니다).
class SomeClass {
constructor() {}
}
var someClassInstance = new SomeClass();
someClassInstance.constructor.name; // === 'SomeClass'
SomeClass.name // === 'SomeClass'
최신 정보
바벨은 괜찮 았지만, 어설픈 / 최소화로 인해 문제가 발생했습니다. 게임을 만들고 있으며 풀링 된 Sprite 리소스의 해시 (키가 함수 이름 임)를 만들고 있습니다. 축소 후 모든 함수 / 클래스의 이름이로 지정되었습니다 t
. 해시가 종료됩니다. 나는 Gulp
이 프로젝트에서 사용하고 있으며 gulp-uglify 문서를 읽은 후이 로컬 변수 / 함수 이름이 엉망이되는 것을 막는 매개 변수가 있음을 발견했습니다. 그래서 내 gulpfile에서 변경했습니다
.pipe($.uglify())
에 .pipe($.uglify({ mangle: false }))
여기에는 성능과 가독성의 균형이 있습니다. 이름을 조작하지 않으면 (약간) 더 큰 빌드 파일 (더 많은 네트워크 리소스)과 잠재적으로 코드 실행 속도가 느려질 수 있습니다 (인용 필요-BS 일 수 있음). 반면에 동일하게 유지하면 getClassName
모든 ES6 클래스에서 정적 및 인스턴스 수준 으로 수동으로 정의해야 합니다. 고맙지 만 사양 할게!
최신 정보
의견에 대한 토론 후에는 .name
그러한 기능을 정의하는 데 유리한 관례를 피하는 것이 좋은 패러다임입니다. 몇 줄의 코드 만 필요하며 라이브러리에서 사용하는 경우 코드의 전체 축소 및 일반성을 허용합니다. 그래서 나는 내 마음을 바꾸고 getClassName
수업에 수동으로 정의 할 것 같아요 . 감사합니다 @estus! . Getter / Setter는 일반적으로 특히 클라이언트 기반 응용 프로그램에서 직접 가변 액세스에 비해 좋은 아이디어입니다.
class SomeClass {
constructor() {}
static getClassName(){ return 'SomeClass'; }
getClassName(){ return SomeClass.getClassName(); }
}
var someClassInstance = new SomeClass();
someClassInstance.constructor.getClassName(); // === 'SomeClass' (static fn)
someClassInstance.getClassName(); // === 'SomeClass' (instance fn)
SomeClass.getClassName() // === 'SomeClass' (static fn)
답변
클래스에서 직접 클래스 이름 가져 오기
이전 답변 someClassInstance.constructor.name
에서는 잘 작동하지만 프로그래밍 방식으로 클래스 이름을 문자열로 변환해야하고 인스턴스를 만들고 싶지 않은 경우 다음을 기억하십시오.
typeof YourClass === "function"
그리고 모든 함수에는 name
속성 이 있으므로 클래스 이름으로 문자열을 얻는 또 다른 좋은 방법은 다음과 같습니다.
YourClass.name
다음은 이것이 왜 유용한 지에 대한 좋은 예입니다.
웹 구성 요소로드
MDN 설명서에서 알 수 있듯이 웹 구성 요소를로드하는 방법은 다음과 같습니다.
customElements.define("your-component", YourComponent);
YourComponent
에서 확장되는 클래스는 어디 입니까 HTMLElement
? 컴포넌트 태그 자체 다음에 컴포넌트 클래스 이름을 지정하는 것이 좋은 방법으로 간주되므로 모든 컴포넌트가 자신을 등록하는 데 사용할 수있는 도우미 함수를 작성하는 것이 좋습니다. 그 기능은 다음과 같습니다.
function registerComponent(componentClass) {
const componentName = upperCamelCaseToSnakeCase(componentClass.name);
customElements.define(componentName, componentClass);
}
따라서 필요한 것은 다음과 같습니다.
registerComponent(YourComponent);
구성 요소 태그를 직접 작성하는 것보다 오류가 덜 발생하기 때문에 좋습니다. 요약하면 다음과 같은 upperCamelCaseToSnakeCase()
기능입니다.
// converts `YourString` into `your-string`
function upperCamelCaseToSnakeCase(value) {
return value
// first char to lower case
.replace(/^([A-Z])/, $1 => $1.toLowerCase())
// following upper chars get preceded with a dash
.replace(/([A-Z])/g, $1 => "-" + $1.toLowerCase());
}
답변
바벨 트랜스 필 레이션 (최소화 전)
와 함께 Babel을 사용하는 경우 @babel/preset-env
클래스 정의를 함수로 변환하지 않고 클래스 정의를 유지할 수 있습니다 ( constructor
속성 제거 ).
이 구성에 대한 오래된 브라우저 호환성을 다음에서 제거 할 수 있습니다 babel.config / babelrc
.
{
"presets": [
["@babel/preset-env", {"targets": {"browsers": ["> 2%"]}}]
]
}
다음에 대한 추가 정보
targets
: https://babeljs.io/docs/en/babel-preset-env#targets
바벨 축소 (트랜스 필 레이션 후)
지금은 쉬운 해결책이없는 것 같습니다 … 우리는 배제를 다루어야합니다.