JavaScript 객체의 클래스를 얻는 방법?


728

JavaScript 객체를 만들었지 만 해당 객체의 클래스를 어떻게 확인할 수 있습니까?

Java의 .getClass()방법 과 비슷한 것을 원합니다 .


6
예를 들어 다음과 같이 Person을 만듭니다. var p = new Person (); "p"라는 Person Object가 있는데 "p"를 사용하여 클래스 이름 "Person"을 다시 얻는 방법은 무엇입니까?
DNB5brims


업데이트 : ECMAScript 6부터 JavaScript에는 여전히 class유형 이 없습니다 . 그것은 않습니다class키워드 class의 방법이 할 수있는 더 쉽게 액세스 프로토 타입을 만들기위한 구문을 super.
james_womack 3

Object.className은 어떻습니까?
Paul Basenko 2012

@ Paul-Basenko : "className"은 객체의 클래스를 알려주지 않지만 CSS 클래스를 참조하는 HTML 요소의 "class"속성의 내용을 반환합니다. 또한 "classList"를 사용하여 쉽게 관리하고 싶지만 OP의 질문과 관련이 없습니다.
흑요석

답변:


1009

getClass()JavaScript 에는 Java와 정확히 일치하는 것이 없습니다 . 자바는 클래스 기반 언어 가 아닌 프로토 타입 기반 언어 이기 때문 입니다.

필요한 것에 따라 getClass()JavaScript에는 몇 가지 옵션이 있습니다.

몇 가지 예 :

function Foo() {}
var foo = new Foo();

typeof Foo;             // == "function"
typeof foo;             // == "object"

foo instanceof Foo;     // == true
foo.constructor.name;   // == "Foo"
Foo.name                // == "Foo"    

Foo.prototype.isPrototypeOf(foo);   // == true

Foo.prototype.bar = function (x) {return x+x;};
foo.bar(21);            // == 42

참고 : Uglify로 코드를 컴파일하는 경우 비전 역 클래스 이름이 변경됩니다. 이를 방지하기 위해, 추하게는이 --mangle사용되어 false로 설정할 수 PARAM 꿀꺽 또는 불평 소리를 .


6
아마도 func.prototype그렇습니다 (예, 함수는 객체이지만 prototype속성은 함수 객체에만 관련이 있습니다).
Miles

5
또한 instanceof/ / isPrototypeOf()비표준 을 언급하고 싶을 수도 있습니다__proto__
Christoph

9
ES5도 추가로Object.getPrototypeOf()
Christoph

22
경고 : constructor.name코드가 축소되는 경우 의존하지 마십시오 . 기능 이름은 임의로 변경됩니다.
igorsantos07

3
2019 년 최소 @ igorsantos07; "온라인 자바 스크립트 축소 기"에 대한 상위 5-10 개의 Google 검색 결과는 construction.name무시하거나 최소화하지 않을 토큰으로 인식 합니다. 대부분의 축소 기 소프트웨어 외에도 예외 규칙이 제공됩니다.
vulcan raven

296
obj.constructor.name

최신 브라우저에서 신뢰할 수있는 방법입니다. Function.nameES6 표준에 공식적으로 추가되어 JavaScript 객체의 "클래스"를 문자열로 가져 오는 표준 준수 수단이되었습니다. 객체가로 인스턴스화되면 var obj = new MyClass()"MyClass"가 반환됩니다.

숫자에 대해서는 "Number", 배열에 대해서는 "Array", 함수에 대해서는 "Function"등을 반환합니다. 일반적으로 예상대로 동작합니다. 프로토 타입이나 via없이 객체를 만들 Object.create( null )거나 익명으로 정의 된 (이름이없는) 함수에서 객체를 인스턴스화 한 경우에만 실패 합니다.

또한 코드를 축소하는 경우 하드 코딩 된 유형 문자열과 비교하는 것이 안전하지 않습니다. 예를 들어 확인하는 obj.constructor.name == "MyType"대신 확인하십시오 obj.constructor.name == MyType.name. 또는 생성자 자체를 비교하면 각 DOM에 생성자 함수의 다른 인스턴스가 있으므로 생성자에 대한 객체 비교를 수행 할 수 없으므로 DOM 경계를 넘어서 작동하지 않습니다.


11
Function.name(아직) JavaScript 표준의 일부가 아닙니다. 현재 Chrome 및 Firefox에서는 지원되지만 IE (10)에서는 지원되지 않습니다.
Halcyon

13
obj.constructor.name명명 된 함수에 대해서만 작동 합니다. 즉, 나는 정의하면 var Foo = function() {}, 다음에 var foo = new Foo(), foo.constructor.name당신은 빈 문자열을 제공 할 것입니다.
KFL

29
경고 : constructor.name코드가 축소되는 경우 의존하지 마십시오 . 기능 이름은 임의로 변경됩니다.
igorsantos07


1
@adalbertpl ES6 이전에는 수동 체인 프로토 타입과 관련이있었습니다. constructor.nameES6의 새로운 클래스 지원으로 예상대로 작동하는 것이 좋습니다 .
devios1

29

이 함수는 "Undefined"정의되지 않은 값과 "Null"null을 반환 합니다 .
다른 모든 값의 경우 CLASSNAME-part가에서 추출되어 [object CLASSNAME]사용 Object.prototype.toString.call(value)됩니다.

function getClass(obj) {
  if (typeof obj === "undefined") return "Undefined";
  if (obj === null) return "Null";
  return Object.prototype.toString.call(obj).match(/^\[object\s(.*)\]$/)[1];
}

getClass("")   === "String";
getClass(true) === "Boolean";
getClass(0)    === "Number";
getClass([])   === "Array";
getClass({})   === "Object";
getClass(null) === "Null";
// etc...

Object.prototype.getClass = function () {obj 대신 'this'를 사용하면 좋을 것입니다
SparK

2
물론 Object 만 getClass 메소드를 가지기 때문에 null과 undefined를 체크 할 수 없습니다
SparK

8
이것은 기본 객체에서만 작동합니다. 어떤 종류의 상속이 있다면 항상 얻을 "Object"것이다.
Halcyon

예, 함수의 마지막 줄은이어야합니다 return obj.constructor.name. 이는 동일한 결과를 제공하며 기본이 아닌 객체도 처리합니다.
Steve Bennett

18

"의사 클래스"를 얻으려면 다음과 같이 생성자 함수를 얻을 수 있습니다.

obj.constructor

constructor상속을 할 때가 올바르게 설정 되었다고 가정하면 다음과 같습니다.

Dog.prototype = new Animal();
Dog.prototype.constructor = Dog;

이 두 줄은

var woofie = new Dog()

woofie.constructor가리킬 것 Dog입니다. 참고 Dog생성자 함수이며,이다 Function객체입니다. 그러나 당신은 할 수 있습니다 if (woofie.constructor === Dog) { ... }.

클래스 이름을 문자열로 얻으려면 다음이 잘 작동합니다.

http://blog.magnetiq.com/post/514962277/finding-out-class-names-of-javascript-objects

function getObjectClass(obj) {
    if (obj && obj.constructor && obj.constructor.toString) {
        var arr = obj.constructor.toString().match(
            /function\s*(\w+)/);

        if (arr && arr.length == 2) {
            return arr[1];
        }
    }

    return undefined;
}

생성자 함수를 가져 와서 문자열로 변환하고 생성자 함수의 이름을 추출합니다.

참고는 obj.constructor.name잘 작동 수도 있지만, 표준이 아니다. Chrome 및 Firefox에는 있지만 IE 9 또는 IE 10 RTM을 포함한 IE에는 없습니다.


13

constructor 속성 을 사용하여 객체를 만든 생성자 함수에 대한 참조를 얻을 수 있습니다 .

function MyObject(){
}

var obj = new MyObject();
obj.constructor; // MyObject

런타임에 객체 유형을 확인해야하는 경우 instanceof 연산자를 사용할 수 있습니다 .

obj instanceof MyObject // true

생성자 함수 자체를 반환하지 않습니다. 다시 호출하여 해당 유형의 새 객체를 만들 수 있습니까?
SparK

1
@SparK 예. 동일한 DOM에있는 한 (함수 객체를 비교하는 경우) 여전히 비교에 사용할 수 있습니다. 그러나 생성자를 문자열로 바꾸고 비교하는 것이 훨씬 좋습니다. 특히 iframe을 사용할 때 DOM 경계에서 작동하기 때문입니다.
devios1

이 대답은 "클래스"(또는 적어도 클래스의 인스턴스를 만드는 데 사용할 수있는 개체 핸들- "클래스"와 동일)를 반환합니다. 위의 내용은 "클래스 객체"와 동일하지 않은 모든 반환 된 문자열에 응답합니다.
Mike P.

8

이전 버전과의 호환성 인 ECMAScript 6에 대한 끊임없는 기록을 유지하면서 JavaScript는 여전히 class유형을 갖지 않습니다 (모두가 이것을 이해하는 것은 아님). 그것은 않습니다class자사의 일환으로 키워드 class프로토 타입 -하지만 작성하기위한 구문 여전히 클래스라는 어떤 일을 . JavaScript는 지금은 아니고 고전적인 OOP 언어 가 아닙니다 . 클래스 측면에서 JS에 대해 말하는 것은 오해의 소지가 있거나 아직 프로토 타입 상속을하지 않은 징후 일뿐입니다 (실제로 유지).

이는 this.constructor여전히 constructor함수에 대한 참조를 얻는 좋은 방법 입니다. 그리고 this.constructor.prototype프로토 타입 자체에 액세스하는 방법입니다. 이것은 자바가 아니기 때문에 클래스가 아닙니다. 인스턴스가 인스턴스화 된 프로토 타입 객체입니다. 다음은 프로토 타입 체인을 만들기 위해 ES6 구문 설탕을 사용하는 예입니다.

class Foo {
  get foo () {
    console.info(this.constructor, this.constructor.name)
    return 'foo'
  }
}

class Bar extends Foo {
  get foo () {
    console.info('[THIS]', this.constructor, this.constructor.name, Object.getOwnPropertyNames(this.constructor.prototype))
    console.info('[SUPER]', super.constructor, super.constructor.name, Object.getOwnPropertyNames(super.constructor.prototype))

    return `${super.foo} + bar`
  }
}

const bar = new Bar()
console.dir(bar.foo)

이것이 다음을 사용하여 출력되는 것입니다 babel-node.

> $ babel-node ./foo.js                                                                                                                    6.2.0 master ●]
[THIS] [Function: Bar] 'Bar' [ 'constructor', 'foo' ]
[SUPER] [Function: Foo] 'Foo' [ 'constructor', 'foo' ]
[Function: Bar] 'Bar'
'foo + bar'

거기 있어요! 2016 년에는 classJavaScript에 키워드가 있지만 클래스 유형은 없습니다. this.constructor생성자 함수 this.constructor.prototype를 얻는 가장 좋은 방법이며 프로토 타입 자체에 액세스하는 가장 좋은 방법입니다.


7

나는 지금 일반적인 일을하고 이것을 사용했다 :

class Test {
  // your class definition
}

nameByType = function(type){
  return type.prototype["constructor"]["name"];
};

console.log(nameByType(Test));

그것이 객체의 인스턴스가없는 경우 유형 입력으로 클래스 이름을 얻는 유일한 방법입니다.

(ES2017로 작성)

도트 표기법도 잘 작동합니다

console.log(Test.prototype.constructor.name); // returns "Test" 

아 내가 찾던 것입니다. 인스턴스화되지 않은 경우 'prototype'을 사용하여 클래스 이름을 가져와야합니다. 정말 감사합니다!
Artokun

4

ES6의 Javascript 클래스의 경우을 사용할 수 있습니다 object.constructor. 아래 예제 클래스에서 getClass()메소드는 예상대로 ES6 클래스를 리턴합니다.

var Cat = class {

    meow() {

        console.log("meow!");

    }

    getClass() {

        return this.constructor;

    }

}

var fluffy = new Cat();

...

var AlsoCat = fluffy.getClass();
var ruffles = new AlsoCat();

ruffles.meow();    // "meow!"

getClass메소드 에서 클래스를 인스턴스화하는 경우 클래스를 괄호로 묶어야합니다. 예 :ruffles = new ( fluffy.getClass() )( args... );


3

chome으로 반환 되지 않고 IE에서 object.constructor.toString()반환 [object objectClass]을 찾습니다 function objectClass () {}. 따라서 http://blog.magnetiq.com/post/514962277/finding-out-class-names-of-javascript-objects 의 코드 가 IE에서 제대로 작동하지 않을 수 있다고 생각합니다. 그리고 코드를 다음과 같이 수정했습니다.

암호:

var getObjectClass = function (obj) {
        if (obj && obj.constructor && obj.constructor.toString()) {

                /*
                 *  for browsers which have name property in the constructor
                 *  of the object,such as chrome 
                 */
                if(obj.constructor.name) {
                    return obj.constructor.name;
                }
                var str = obj.constructor.toString();
                /*
                 * executed if the return of object.constructor.toString() is 
                 * "[object objectClass]"
                 */

                if(str.charAt(0) == '[')
                {
                        var arr = str.match(/\[\w+\s*(\w+)\]/);
                } else {
                        /*
                         * executed if the return of object.constructor.toString() is 
                         * "function objectClass () {}"
                         * for IE Firefox
                         */
                        var arr = str.match(/function\s*(\w+)/);
                }
                if (arr && arr.length == 2) {
                            return arr[1];
                        }
          }
          return undefined; 
    };

2

자바 스크립트에는 클래스가 없지만 생성자 이름을 원한다고 생각하고 obj.constructor.toString()필요한 것을 알려줍니다.


1
생성자 함수의 전체 정의를 문자열로 반환합니다. 당신이 정말로 원하는 것은 .name입니다.
devios1

4
그러나 .name심지어 IE 9에 정의되어 있지 않습니다
nonopolarity

1

dfa에 동의하십시오. 그래서 명명 된 클래스를 찾을 수 없을 때 프로토 타입을 클래스로 간주합니다.

Eli Grey가 게시 한 기능을 업그레이드하여 내 마음에 맞 춥니 다.

function what(obj){
    if(typeof(obj)==="undefined")return "undefined";
    if(obj===null)return "Null";
    var res = Object.prototype.toString.call(obj).match(/^\[object\s(.*)\]$/)[1];
    if(res==="Object"){
        res = obj.constructor.name;
        if(typeof(res)!='string' || res.length==0){
            if(obj instanceof jQuery)return "jQuery";// jQuery build stranges Objects
            if(obj instanceof Array)return "Array";// Array prototype is very sneaky
            return "Object";
        }
    }
    return res;
}

1

GET 클래스뿐만 아니라 인스턴스가 없어도 확장하려면 다음과 같이 작성하십시오.

하자

 class A{ 
   constructor(name){ 
     this.name = name
   }
 };

 const a1 = new A('hello a1');

따라서 인스턴스 만 사용하도록 A를 확장하려면 다음을 사용하십시오.

const a2 = new ((Object.getPrototypeOf(a)).constructor())('hello a2')
// the analog of const a2 = new A()

console.log(a2.name)//'hello a2'

0

나는 다음을 사용하는 것이 좋습니다 Object.prototype.constructor.name.

Object.defineProperty(Object.prototype, "getClass", {
    value: function() {
      return this.constructor.name;
    }
});

var x = new DOMParser();
console.log(x.getClass()); // `DOMParser'

var y = new Error("");
console.log(y.getClass()); // `Error'

0

다음의 구현입니다 getClass()getInstance()

를 사용하여 객체의 클래스에 대한 참조를 얻을 수 있습니다 this.constructor.

인스턴스 컨텍스트에서 :

function A() {
  this.getClass = function() {
    return this.constructor;
  }

  this.getNewInstance = function() {
    return new this.constructor;
  }
}

var a = new A();
console.log(a.getClass());  //  function A { // etc... }

// you can even:
var b = new (a.getClass());
console.log(b instanceof A); // true
var c = a.getNewInstance();
console.log(c instanceof A); // true

정적 컨텍스트에서 :

function A() {};

A.getClass = function() {
  return this;
}

A.getInstance() {
  return new this;
}

2
왜 안돼 this.constructor?
Solomon Ucko

1
잘 모르겠지만, 그것이 더 낫다면, 당신이 더 나은 것을 찾은대로 답을 편집하여 개선 할 수 있습니다.
Bruno Finger

0

이런 식으로도 할 수 있습니다

 class Hello {
     constructor(){
     }
    }
    
      function isClass (func) {
        return typeof func === 'function' && /^class\s/.test(Function.prototype.toString.call(func))
    }
    
   console.log(isClass(Hello))

입력이 클래스인지 아닌지를 알려줍니다.


-2

Javascript는 클래스가없는 언어입니다. Java에서와 같이 클래스의 동작을 정적으로 정의하는 클래스는 없습니다. JavaScript는 클래스 대신 프로토 타입을 사용하여 메서드 및 상속을 포함한 객체 속성을 정의합니다. JavaScript에서 프로토 타입을 사용하여 많은 클래스 기반 기능을 시뮬레이션 할 수 있습니다.


12
나는 종종 자바 스크립트에 클래스가 없다고 말했다 :)
Steven

4
업데이트 : ECMAScript 6부터 JavaScript에는 여전히 class유형 이 없습니다 . 그것은 않습니다class키워드 class의 방법이 할 수있는 더 쉽게 액세스 프로토 타입을 만들기위한 구문을 super.
james_womack

-3

질문은 이미 답변 된 것처럼 보이지만 OP는 Java에서와 마찬가지로 클래스와 객체에 액세스하려고하며 선택한 답변이 충분하지 않습니다 (imho).

다음 설명을 통해 객체의 클래스를 얻을 수 있습니다 (실제로는 자바 스크립트에서 프로토 타입이라고 함).

var arr = new Array('red', 'green', 'blue');
var arr2 = new Array('white', 'black', 'orange');

다음과 같은 속성을 추가 할 수 있습니다.

Object.defineProperty(arr,'last', {
  get: function(){
    return this[this.length -1];
  }
});
console.log(arr.last) // blue

그러나 .last속성은 arrArray 프로토 타입에서 인스턴스화 된 ' '객체 에만 사용할 수 있습니다 . 따라서 .lastArray 프로토 타입에서 인스턴스화 된 모든 객체에 속성을 사용할 수 있으려면 .lastArray 프로토 타입에 대한 속성 을 정의해야 합니다.

Object.defineProperty(Array.prototype,'last', {
  get: function(){
    return this[this.length -1];
  }
});
console.log(arr.last) // blue
console.log(arr2.last) // orange

여기서 문제는 ' arr'및 ' arr2'변수가 속하는 객체 유형 (프로토 타입)을 알아야 한다는 것입니다! 즉, ' arr'객체 의 클래스 유형 (프로토 타입)을 모르면 해당 속성을 정의 할 수 없습니다. 위의 예에서 arr은 Array 객체의 인스턴스라는 것을 알고 있으므로 Array.prototype을 사용하여 Array의 속성을 정의했습니다. 그러나 ' arr' 의 클래스 (프로토 타입)를 모른다면 어떻게해야 합니까?

Object.defineProperty(arr.__proto__,'last2', {
  get: function(){
    return this[this.length -1];
  }
});
console.log(arr.last) // blue
console.log(arr2.last) // orange

보시다시피, ' arr'이 배열이라는 것을 몰라도 우리는 ' arr'를 사용하여 ' arr.__proto__' 의 클래스를 참조하는 bu라는 새로운 속성을 추가 할 수 있습니다 .

우리 arr는 어레이의 인스턴스라는 것을 알지 못하고 ' ' 의 프로토 타입에 액세스했으며 이것이 OP가 요청한 것이라고 생각합니다.


__proto__속성은 더 이상 사용되지 않으며 속성보다 거의 이점이 없습니다 prototype.
Sapphire_Brick
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.