[javascript] ES6 클래스 인스턴스의 클래스 이름을 가져옵니다.

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이 작업을 수행하는 올바른 방법입니다. 트랜스 파일러는이를 지원하지 않을 수 있지만 사양에 따라 표준 방식입니다. ( nameClassDeclaration 프로덕션을 통해 선언 된 함수 의 특성은 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

바벨 축소 (트랜스 필 레이션 후)

지금은 쉬운 해결책이없는 것 같습니다 … 우리는 배제를 다루어야합니다.


답변