객체 타입의 이름을 얻는다


1193

거기에 자바 스크립트 의 해당하는 자바 의는 class.getName()?


이 질문은 Java의 class.getName ()이 무엇을 하는지를 알고 있다고 가정합니다. 답변이 도움이 될지 확실하지 않기 때문에.
user34660

2
@ user34660 객체 유형의 이름을 얻는 것이 안전하다고 가정 할 수 있다고 생각합니다.
Stack Underflow

1
@StackUnderflow : 실제로는 그렇지 않습니다. 그것은 개체의 이름 얻는 클래스 이며, 하지 객체의 동일한 유형을 .
Jörg W Mittag

1
@ JörgWMittag 물론입니다. 나중에 안전하게 가정을 돌아 다닐 때 어떤 일이 발생하는지 봅니까?
Stack Underflow

답변:


1540

Java와 동등한 JavaScript가 class.getName()있습니까?

없음 .

ES2015 업데이트 : 의 이름은 class Foo {}입니다Foo.name . 유형에 thing관계없이 클래스 이름은 thing입니다 thing.constructor.name. ES2015 환경의 내장 생성자는 올바른 name속성을 갖습니다 . 예를 들어 (2).constructor.name입니다 "Number".


그러나 여러 가지 해킹이 있습니다.

다음은 필요한 작업을 수행하는 해킹입니다. 개체의 프로토 타입, 사람들이 겪고있는 무언가 (보통 정당한 이유)를 수정합니다.

Object.prototype.getName = function() { 
   var funcNameRegex = /function (.{1,})\(/;
   var results = (funcNameRegex).exec((this).constructor.toString());
   return (results && results.length > 1) ? results[1] : "";
};

이제 모든 객체 getName()에 생성자 이름을 문자열로 반환하는 함수가 있습니다 . 나는이 테스트 한 FF3하고 IE7, 나는 다른 구현을 말할 수 없다.

그렇게하고 싶지 않다면 JavaScript에서 유형을 결정하는 다양한 방법에 대해 설명합니다 ...


나는 최근에 이것을 조금 더 철저하게 업데이트했지만, 거의 그렇지 않습니다. 정정을 환영합니다 ...

constructor속성 사용 중 ...

모든 사람 object은 그 constructor속성에 대한 가치를 가지고 있지만 그것이 어떻게 만들어 object졌는지와 그 가치로 무엇을하고 싶은지에 따라 유용 할 수도 있고 그렇지 않을 수도 있습니다.

일반적으로 constructor속성을 사용하여 다음과 같이 객체 유형을 테스트 할 수 있습니다 .

var myArray = [1,2,3];
(myArray.constructor == Array); // true

따라서 대부분의 요구에 충분합니다. 그건 ...

경고

작동하지 않습니다 AT ALL을 많은 경우에

이 패턴은 깨졌지만 매우 일반적입니다.

function Thingy() {
}
Thingy.prototype = {
    method1: function() {
    },
    method2: function() {
    }
};

Objects를 통해 생성 new Thingyconstructor속성은을 가리키는 속성을 가지지 Object않습니다 Thingy. 그래서 우리는 처음에 빠졌습니다. constructor제어하지 않는 코드베이스를 신뢰할 수 없습니다 .

다중 상속

분명하지 않은 예는 다중 상속을 사용하는 것입니다.

function a() { this.foo = 1;}
function b() { this.bar = 2; }
b.prototype = new a(); // b inherits from a

다음과 같이 예상 한대로 작동하지 않습니다.

var f = new b(); // instantiate a new object with the b constructor
(f.constructor == b); // false
(f.constructor == a); // true

따라서 object테스트의 object설정 이 다른 경우 예기치 않은 결과가 발생할 수 있습니다 prototype. 이 논의의 범위를 벗어나는 방법에는 여러 가지가 있습니다.

constructor재산에 대한 다른 용도가 있으며 , 그중 일부는 흥미롭고 다른 것은 그다지 중요하지 않습니다. 지금까지는이 논의와 관련이 없기 때문에 이러한 용도에 대해서는 다루지 않겠습니다.

크로스 프레임 및 크로스 윈도우에서 작동하지 않습니다

사용하여 .constructor서로 다른에서 오는 객체의 종류를 확인하고자 할 때 중단됩니다 유형 검사에 대한 window개체를 iframe이 또는 팝업 윈도우의 말. constructor각`윈도우 ' 에 각 코어 유형의 버전이 다르기 때문입니다.

iframe.contentWindow.Array === Array // false

instanceof연산자 사용 ...

instanceof운영자는 테스트의 깨끗한 방법입니다 object단지처럼뿐만 아니라 유형을하지만, 자신의 잠재적 인 문제를 가지고 constructor속성입니다.

var myArray = [1,2,3];
(myArray instanceof Array); // true
(myArray instanceof Object); // true

그러나 instanceof리터럴 값에 대해서는 작동하지 않습니다 (리터럴이 아니기 때문에 Objects)

3 instanceof Number // false
'abc' instanceof String // false
true instanceof Boolean // false

리터럴은에 싸여해야 Object위해서는 instanceof예를 들어, 작업에

new Number(3) instanceof Number // true

.constructor때문에 검사는 리터럴에 대한 벌금을 작동하는 .메소드 호출은 암시 적으로 각각의 객체 타입의 리터럴을 래핑

3..constructor === Number // true
'abc'.constructor === String // true
true.constructor === Boolean // true

왜 3에 두 개의 점이 있습니까? Javascript는 첫 번째 점을 소수점으로 해석하기 때문에;)

크로스 프레임 및 크로스 윈도우에서 작동하지 않습니다

instanceofconstructor속성 확인 과 같은 이유로 다른 창에서도 작동하지 않습니다 .


name속성의 속성을 사용하여 constructor...

작동하지 않습니다 AT ALL을 많은 경우에

다시, 위 참조; constructor완전히 잘못되고 쓸모가없는 것이 일반적입니다 .

<IE9에서 작동하지 않습니다

사용하면 사용 myObjectInstance.constructor.nameconstructor함수 의 이름이 포함 된 문자열이 제공 되지만 constructor앞에서 언급 한 속성 에 대한 경고가 적용됩니다 .

IE9 이상에서는 다음과 같이 원숭이 패치를 지원할 수 있습니다 .

if (Function.prototype.name === undefined && Object.defineProperty !== undefined) {
    Object.defineProperty(Function.prototype, 'name', {
        get: function() {
            var funcNameRegex = /function\s+([^\s(]+)\s*\(/;
            var results = (funcNameRegex).exec((this).toString());
            return (results && results.length > 1) ? results[1] : "";
        },
        set: function(value) {}
    });
}

해당 기사의 버전이 업데이트되었습니다 . 이것은 기사가 출판 된 지 3 개월 후에 추가되었으며,이 기사의 저자 Matthew Scharley가 권장하는 버전입니다. 이 변경은 이전 코드의 잠재적 함정지적 하는 의견 에서 영감을 얻었습니다 .

if (Function.prototype.name === undefined && Object.defineProperty !== undefined) {
    Object.defineProperty(Function.prototype, 'name', {
        get: function() {
            var funcNameRegex = /function\s([^(]{1,})\(/;
            var results = (funcNameRegex).exec((this).toString());
            return (results && results.length > 1) ? results[1].trim() : "";
        },
        set: function(value) {}
    });
}

Object.prototype.toString 사용

이 게시물 세부 사항 에서 알 수 있듯이 Object.prototype.toString낮은 수준의 일반 구현을 사용 toString하여 모든 내장 유형의 유형을 얻을 수 있습니다

Object.prototype.toString.call('abc') // [object String]
Object.prototype.toString.call(/abc/) // [object RegExp]
Object.prototype.toString.call([1,2,3]) // [object Array]

다음과 같은 짧은 도우미 함수를 작성할 수 있습니다.

function type(obj){
    return Object.prototype.toString.call(obj).slice(8, -1);
}

부스러기를 제거하고 유형 이름 만 얻으십시오.

type('abc') // String

그러나 Object모든 사용자 정의 유형에 대해 반환 됩니다.


모든주의 사항 ...

이 모든 것들은 하나의 잠재적 인 문제에 영향을받으며, 문제의 대상이 어떻게 구성되었는지에 대한 문제입니다. 다음은 객체를 빌드하는 다양한 방법과 다양한 유형 검사 방법이 반환하는 값입니다.

// using a named function:
function Foo() { this.a = 1; }
var obj = new Foo();
(obj instanceof Object);          // true
(obj instanceof Foo);             // true
(obj.constructor == Foo);         // true
(obj.constructor.name == "Foo");  // true

// let's add some prototypical inheritance
function Bar() { this.b = 2; }
Foo.prototype = new Bar();
obj = new Foo();
(obj instanceof Object);          // true
(obj instanceof Foo);             // true
(obj.constructor == Foo);         // false
(obj.constructor.name == "Foo");  // false


// using an anonymous function:
obj = new (function() { this.a = 1; })();
(obj instanceof Object);              // true
(obj.constructor == obj.constructor); // true
(obj.constructor.name == "");         // true


// using an anonymous function assigned to a variable
var Foo = function() { this.a = 1; };
obj = new Foo();
(obj instanceof Object);      // true
(obj instanceof Foo);         // true
(obj.constructor == Foo);     // true
(obj.constructor.name == ""); // true


// using object literal syntax
obj = { foo : 1 };
(obj instanceof Object);            // true
(obj.constructor == Object);        // true
(obj.constructor.name == "Object"); // true

이 예제 세트에 모든 순열이있는 것은 아니지만, 필요에 따라 지저분한 일이 어떻게 발생할 지에 대한 아이디어를 제공하기에 충분합니다. 아무 것도 생각하지 마십시오. 뒤에 무엇이 있는지 정확히 이해하지 못하면 미묘한 실수로 인해 예상치 못한 코드가 깨질 수 있습니다.

노트:

typeof연산자에 대한 논의는 눈부신 누락으로 보이지만 실제로는 object주어진 유형 인지 여부를 식별하는 데 도움이되지 않습니다 . 매우 단순하기 때문입니다. typeof유용한 부분을 ​​이해하는 것이 중요하지만 현재는이 토론과 관련이 있다고 생각하지 않습니다. 그래도 마음이 바뀌어 열려 있습니다. :)


58
글쎄, 내가 할 수도 있다고 생각했다. 스택 오버플로의 요점은 위키와 비슷해야하며, 이것은 그 의도와 훨씬 더 일치한다고 생각합니다. 어쨌든, 나는 다소 철저하고 싶었습니다.
Jason Bunting

IE8에서는 Object 프로토 타입에 대한 확장 기능이 작동하지 않습니다. IE8에서 무엇이 작동하는지 아는 사람이 있습니까?
Adam

5
다음과 같이하면 작동합니다. a () {this.a = 1;} function b () {this.b = 2; } b.prototype = 새 a (); // b는 b.prototype.constructor에서 상속합니다. = b; // 올바른 프로토 타입 상속 방법 var f = new b (); // b 생성자로 새 객체를 만듭니다 (f.constructor == b); // 참 (f.constructor == a); // FALSE
Boris Hamanov

9
이제 이것이 대부분의 답변이 StackOverflow에 있어야하는 방법입니다. (답변의 길이를 정의 매개 변수로 사용하지 말고 포괄적으로 고려하십시오)
kumarharsh

44
Javascript가 uglify 또는 Rails 자산 파이프 라인과 같은 도구로 축소 된 경우 객체의 constructor방법 ( .toString()또는로 .name) 을 검사하는 모든 기법이 작동하지 않는다는 점에 유의해야합니다 . 축소는 생성자의 이름을 바꾸므로와 같은 잘못된 클래스 이름으로 끝납니다 n. 이 시나리오에 있다면 객체에 속성을 수동으로 정의하고 className대신 사용할 수 있습니다.
Gabe Martin-Dempesy

126

Jason Bunting의 대답은 내가 필요한 것을 찾을 수있는 충분한 단서를 제공했습니다.

<<Object instance>>.constructor.name

예를 들어, 다음 코드에서

function MyObject() {}
var myInstance = new MyObject();

myInstance.constructor.name반환 "MyObject"합니다.


22
완전성을 위해 constructor.name 사용은 변수에 할당 된 익명 함수가 아닌 명명 된 함수를 생성자로 사용하는 경우에만 작동한다는 것을 언급 할 가치가 있습니다.
Matthew Crumley

20
완전성을 위해, 그것은 IE 브라우저에서 작동하지 않는다는 것을 언급 할 가치가 있습니다 --- 함수에서 "name"속성을 지원하지 않습니다.
유진 Lazutkin

2
@ Eugene-나는 잊어 버렸습니다 ... 브라우저 밖에서 자바 스크립트를하는 데 너무 많은 시간을 보냈습니다.
Matthew Crumley

2
function getType(o) { return o && o.constructor && o.constructor.name }
justin.m.chase

이것은 매우 포괄적입니다.
ibic

26

내가 사용하는 약간의 트릭 :

function Square(){
    this.className = "Square";
    this.corners = 4;
}

var MySquare = new Square();
console.log(MySquare.className); // "Square"

11
나는 이것을 특히 좋아하지 않는다. 좀 더 더러운 속임수입니다. 반면에 생성자가 너무 많지 않으면 제대로 작동 할 수 있습니다.
pimvdb

13
@ pimvdb : 나는 객체의 프로토 타입을 수정하는 것보다 더 깨끗하다고 ​​생각합니다.
Daniel Szabo

4
@DanielSzabo 속성이 프로토 타입의 모든 인스턴스간에 동일한 값을 가져야하는 경우 프로토 타입에 배치하는 것이 좋습니다. 각 인스턴스에 배치하는 것은 중복성이 높으며 메타 데이터는 프로토 타입 자체에서 누락되었습니다. 즉, 현명한 해결책이 ES6에 채택되었다 말했다 : 당신이있는 경우 class Square, 이름이 Square.name/ MySquare.constructor.name가 아니라 Square.prototype.name; 넣어 name생성자 함수에 프로토 타입 또는 인스턴스를 오염시키지 않고, 하나에서 액세스 할 수 있습니다.
Andy

17

최신 정보

정확히 말하면 OP가 특정 객체의 생성자 이름을 검색하는 함수를 요청했다고 생각합니다. Javascript 측면 object에서 유형은 없지만 유형 자체 입니다. 그러나 다른 객체는 다른 생성자를 가질 수 있습니다 .

Object.prototype.getConstructorName = function () {
   var str = (this.prototype ? this.prototype.constructor : this.constructor).toString();
   var cname = str.match(/function\s(\w*)/)[1];
   var aliases = ["", "anonymous", "Anonymous"];
   return aliases.indexOf(cname) > -1 ? "Function" : cname;
}

new Array().getConstructorName();  // returns "Array"
(function () {})().getConstructorName(); // returns "Function"

 


참고 : 아래 예제는 더 이상 사용되지 않습니다.

Christian Sciberras 가 링크 한 블로그 게시물 에는 그 방법에 대한 좋은 예가 있습니다. 즉, Object 프로토 타입을 확장하여

if (!Object.prototype.getClassName) {
    Object.prototype.getClassName = function () {
        return Object.prototype.toString.call(this).match(/^\[object\s(.*)\]$/)[1];
    }
}

var test = [1,2,3,4,5];

alert(test.getClassName()); // returns Array

2
좋습니다. 그러나 우리는 다시 명명 할 것입니다 : JS에는 수업이 없습니다.
mikemaccana 2016 년

@nailer-업데이트 된 기능을 사용하는 것이 좋습니다. 오래된 기능은 단지 역사적인 이유로 유지됩니다.
Saul

이것은 작동하지만 객체를 첫 번째 인수로 사용하고 함수 내에서 'this'대신에 함수를 사용하여 Object.prototype을 수정하지 않고도 수행 할 수 있습니다.
Matt Browne

2
@ 매트-물론. : 그것은 객체 메소드를 가지는 것이 더 간결 단지이다 test.getClassName()getClassName.apply(test).
사울

12

Object.prototype.toString 사용

이 게시물 세부 사항에서 Object.prototype.toString-toString의 저수준 및 일반 구현-을 사용하여 모든 내장 유형의 유형을 얻을 수 있습니다

Object.prototype.toString.call('abc') // [object String]
Object.prototype.toString.call(/abc/) // [object RegExp]
Object.prototype.toString.call([1,2,3]) // [object Array]

다음과 같은 짧은 도우미 함수를 작성할 수 있습니다.

function type(obj){
    return Object.prototype.toString.call(obj]).match(/\s\w+/)[0].trim()
}

return [object String] as String
return [object Number] as Number
return [object Object] as Object
return [object Undefined] as Undefined
return [object Function] as Function

6
정규식을 사용하여 객체 이름을 구문 분석 할 필요는 없습니다. 그냥 사용 .slice():Object.prototype.toString.call(obj).slice( 8, -1 );
보보 보보

9

다음은 instanceof의 단점을 해결하는 해결책입니다. 크로스 윈도우 및 크로스 프레임에서 객체 유형을 확인할 수 있으며 기본 유형에는 문제가 없습니다.

function getType(o) {
    return Object.prototype.toString.call(o).match(/^\[object\s(.*)\]$/)[1];
}
function isInstance(obj, type) {
    var ret = false,
    isTypeAString = getType(type) == "String",
    functionConstructor, i, l, typeArray, context;
    if (!isTypeAString && getType(type) != "Function") {
        throw new TypeError("type argument must be a string or function");
    }
    if (obj !== undefined && obj !== null && obj.constructor) {
        //get the Function constructor
        functionConstructor = obj.constructor;
        while (functionConstructor != functionConstructor.constructor) {
            functionConstructor = functionConstructor.constructor;
        }
        //get the object's window
        context = functionConstructor == Function ? self : functionConstructor("return window")();
        //get the constructor for the type
        if (isTypeAString) {
            //type is a string so we'll build the context (window.Array or window.some.Type)
            for (typeArray = type.split("."), i = 0, l = typeArray.length; i < l && context; i++) {
                context = context[typeArray[i]];
            }
        } else {
            //type is a function so execute the function passing in the object's window
            //the return should be a constructor
            context = type(context);
        }
        //check if the object is an instance of the constructor
        if (context) {
            ret = obj instanceof context;
            if (!ret && (type == "Number" || type == "String" || type == "Boolean")) {
                ret = obj.constructor == context
            }
        }
    }
    return ret;
}

isInstance에는 객체와 유형의 두 매개 변수가 필요합니다. 작동 방식에 대한 실제 요령은 객체가 동일한 창에서 왔는지 여부와 객체의 창을 가져 오지 않는지 확인하는 것입니다.

예 :

isInstance([], "Array"); //true
isInstance("some string", "String"); //true
isInstance(new Object(), "Object"); //true

function Animal() {}
function Dog() {}
Dog.prototype = new Animal();

isInstance(new Dog(), "Dog"); //true
isInstance(new Dog(), "Animal"); //true
isInstance(new Dog(), "Object"); //true
isInstance(new Animal(), "Dog"); //false

type 인수는 생성자를 반환하는 콜백 함수일 수도 있습니다. 콜백 함수는 제공된 객체의 창인 하나의 매개 변수를받습니다.

예 :

//"Arguments" type check
var args = (function() {
    return arguments;
}());

isInstance(args, function(w) {
    return w.Function("return arguments.constructor")();
}); //true

//"NodeList" type check
var nl = document.getElementsByTagName("*");

isInstance(nl, function(w) {
    return w.document.getElementsByTagName("bs").constructor;
}); //true

명심해야 할 것은 IE <9가 모든 객체에 생성자를 제공하지 않기 때문에 위의 NodeList 테스트는 false를 반환하고 isInstance (alert, "Function")도 false를 반환한다는 것입니다.


8

나는 실제로 비슷한 것을 찾고 있었고이 질문을 보았습니다. 다음은 유형을 얻는 방법입니다. jsfiddle

var TypeOf = function ( thing ) {

    var typeOfThing = typeof thing;

    if ( 'object' === typeOfThing ) {

        typeOfThing = Object.prototype.toString.call( thing );

        if ( '[object Object]' === typeOfThing ) {

            if ( thing.constructor.name ) {
                return thing.constructor.name;
            } 

            else if ( '[' === thing.constructor.toString().charAt(0) ) {
                typeOfThing = typeOfThing.substring( 8,typeOfThing.length - 1 );
            } 

            else {

                typeOfThing = thing.constructor.toString().match( /function\s*(\w+)/ );

                if ( typeOfThing ) { 
                    return typeOfThing[1];
                } 

                else {
                    return 'Function';
                }
            }
        } 

        else {
            typeOfThing = typeOfThing.substring( 8,typeOfThing.length - 1 );
        }
    }

    return typeOfThing.charAt(0).toUpperCase() + typeOfThing.slice(1);
}

7

당신은 다음 somevar.constructor.name과 같이 사용해야 합니다 :

    
    const getVariableType = a => a.constructor.name.toLowerCase();

    const d = new Date();
    const res1 = getVariableType(d); // 'date'
    const num = 5;
    const res2 = getVariableType(num); // 'number'
    const fn = () => {};
    const res3 = getVariableType(fn); // 'function'

    console.log(res1); // 'date'
    console.log(res2); // 'number'
    console.log(res3); // 'function'


6

constructor.name할 수있을 때 사용 하고, 할 수 없으면 정규식 기능을 사용하십시오 .

Function.prototype.getName = function(){
  if (typeof this.name != 'undefined')
    return this.name;
  else
    return /function (.+)\(/.exec(this.toString())[1];
};

6

Agave.JSkind () 함수는 다음 을 반환합니다.

  • 상속 트리에서 가장 가까운 프로토 타입
  • 기본 이름 인 'null'및 'undefined'와 같은 항상 기본 유형입니다.

그것은 모든 JS 객체와 프리미티브에서 생성 된 방식에 관계없이 작동하며 놀라움이 없습니다. 예 :

번호

kind(37) === 'Number'
kind(3.14) === 'Number'
kind(Math.LN2) === 'Number'
kind(Infinity) === 'Number'
kind(Number(1)) === 'Number'
kind(new Number(1)) === 'Number'

NaN

kind(NaN) === 'NaN'

kind('') === 'String'
kind('bla') === 'String'
kind(String("abc")) === 'String'
kind(new String("abc")) === 'String'

부울

kind(true) === 'Boolean'
kind(false) === 'Boolean'
kind(new Boolean(true)) === 'Boolean'

배열

kind([1, 2, 4]) === 'Array'
kind(new Array(1, 2, 3)) === 'Array'

사물

kind({a:1}) === 'Object'
kind(new Object()) === 'Object'

날짜

kind(new Date()) === 'Date'

기능

kind(function(){}) === 'Function'
kind(new Function("console.log(arguments)")) === 'Function'
kind(Math.sin) === 'Function'

찾으시는 주소가 없습니다

kind(undefined) === 'undefined'

없는

kind(null) === 'null'

5

instanceof연산자를 사용하여 객체가 다른 객체의 인스턴스인지 확인할 수 있지만 클래스가 없으므로 클래스 이름을 얻을 수 없습니다.


JavaScript에는 언어 구성으로 클래스가없는 것이 사실이지만 일반적인 규칙은 여전히 ​​객체의 유형을 클래스라고하는 것입니다.
Saul

2
@greg 물론이지만 instanceof객체가 다른 객체에서 상속되는지 여부를 확인합니다. 예를 들어 단순 []은 Array에서 상속하지만 Array는 Object에서도 상속합니다. 대부분의 객체에는 여러 수준의 상속이 있으므로 가장 가까운 프로토 타입을 찾는 것이 더 나은 기술입니다. 방법에 대한 내 대답을 참조하십시오.
mikemaccana 12

4

허용되는 답변을 기반으로 한 구현은 다음과 같습니다 .

/**
 * Returns the name of an object's type.
 *
 * If the input is undefined, returns "Undefined".
 * If the input is null, returns "Null".
 * If the input is a boolean, returns "Boolean".
 * If the input is a number, returns "Number".
 * If the input is a string, returns "String".
 * If the input is a named function or a class constructor, returns "Function".
 * If the input is an anonymous function, returns "AnonymousFunction".
 * If the input is an arrow function, returns "ArrowFunction".
 * If the input is a class instance, returns "Object".
 *
 * @param {Object} object an object
 * @return {String} the name of the object's class
 * @see <a href="https://stackoverflow.com/a/332429/14731">https://stackoverflow.com/a/332429/14731</a>
 * @see getFunctionName
 * @see getObjectClass 
 */
function getTypeName(object)
{
  const objectToString = Object.prototype.toString.call(object).slice(8, -1);
  if (objectToString === "Function")
  {
    const instanceToString = object.toString();
    if (instanceToString.indexOf(" => ") != -1)
      return "ArrowFunction";
    const getFunctionName = /^function ([^(]+)\(/;
    const match = instanceToString.match(getFunctionName);
    if (match === null)
      return "AnonymousFunction";
    return "Function";
  }
  // Built-in types (e.g. String) or class instances
  return objectToString;
};

/**
 * Returns the name of a function.
 *
 * If the input is an anonymous function, returns "".
 * If the input is an arrow function, returns "=>".
 *
 * @param {Function} fn a function
 * @return {String} the name of the function
 * @throws {TypeError} if {@code fn} is not a function
 * @see getTypeName
 */
function getFunctionName(fn)
{
  try
  {
    const instanceToString = fn.toString();
    if (instanceToString.indexOf(" => ") != -1)
      return "=>";
    const getFunctionName = /^function ([^(]+)\(/;
    const match = instanceToString.match(getFunctionName);
    if (match === null)
    {
      const objectToString = Object.prototype.toString.call(fn).slice(8, -1);
      if (objectToString === "Function")
        return "";
      throw TypeError("object must be a Function.\n" +
        "Actual: " + getTypeName(fn));
    }
    return match[1];
  }
  catch (e)
  {
    throw TypeError("object must be a Function.\n" +
      "Actual: " + getTypeName(fn));
  }
};

/**
 * @param {Object} object an object
 * @return {String} the name of the object's class
 * @throws {TypeError} if {@code object} is not an Object
 * @see getTypeName
 */
function getObjectClass(object)
{
  const getFunctionName = /^function ([^(]+)\(/;
  const result = object.constructor.toString().match(getFunctionName)[1];
  if (result === "Function")
  {
    throw TypeError("object must be an Object.\n" +
      "Actual: " + getTypeName(object));
  }
  return result;
};


function UserFunction()
{
}

function UserClass()
{
}

let anonymousFunction = function()
{
};

let arrowFunction = i => i + 1;

console.log("getTypeName(undefined): " + getTypeName(undefined));
console.log("getTypeName(null): " + getTypeName(null));
console.log("getTypeName(true): " + getTypeName(true));
console.log("getTypeName(5): " + getTypeName(5));
console.log("getTypeName(\"text\"): " + getTypeName("text"));
console.log("getTypeName(userFunction): " + getTypeName(UserFunction));
console.log("getFunctionName(userFunction): " + getFunctionName(UserFunction));
console.log("getTypeName(anonymousFunction): " + getTypeName(anonymousFunction));
console.log("getFunctionName(anonymousFunction): " + getFunctionName(anonymousFunction));
console.log("getTypeName(arrowFunction): " + getTypeName(arrowFunction));
console.log("getFunctionName(arrowFunction): " + getFunctionName(arrowFunction));
//console.log("getFunctionName(userClass): " + getFunctionName(new UserClass()));
console.log("getTypeName(userClass): " + getTypeName(new UserClass()));
console.log("getObjectClass(userClass): " + getObjectClass(new UserClass()));
//console.log("getObjectClass(userFunction): " + getObjectClass(UserFunction));
//console.log("getObjectClass(userFunction): " + getObjectClass(anonymousFunction));
//console.log("getObjectClass(arrowFunction): " + getObjectClass(arrowFunction));
console.log("getTypeName(nativeObject): " + getTypeName(navigator.mediaDevices.getUserMedia));
console.log("getFunctionName(nativeObject): " + getFunctionName(navigator.mediaDevices.getUserMedia));

우리는 다른 선택이 없을 때에 만 생성자 속성을 사용합니다.


3

"instanceof"연산자를 사용하여 개체가 특정 클래스의 인스턴스인지 여부를 확인할 수 있습니다. 객체 유형의 이름을 모르면 생성자 속성을 사용할 수 있습니다. 객체의 생성자 속성은 객체를 초기화하는 데 사용되는 함수에 대한 참조입니다. 예:

function Circle (x,y,radius) {
    this._x = x;
    this._y = y;
    this._radius = raduius;
}
var c1 = new Circle(10,20,5);

이제 c1.constructor는 Circle()함수에 대한 참조 입니다. typeof운영자를 사용할 수도 있지만 typeof운영자는 제한된 정보를 표시합니다. 한 가지 해결책은 toString()오브젝트 글로벌 오브젝트 의 메소드 를 사용하는 것입니다. 예를 들어 myObject와 같은 객체가있는 경우 toString()전역 객체 의 메소드를 사용하여 myObject 클래스의 유형을 결정할 수 있습니다 . 이것을 사용하십시오 :

Object.prototype.toString.apply(myObject);

3

당신이 가지고 있다고 var obj;

"Object", "Array"또는 "String"과 같은 obj 유형의 이름 만 원하는 경우 다음을 사용할 수 있습니다.

Object.prototype.toString.call(obj).split(' ')[1].replace(']', '');

2

얻을 수있는 가장 가까운 것은입니다 typeof. 그러나 모든 종류의 사용자 정의 유형에 대해서만 "객체"를 반환합니다. 이에 대해서는 Jason Bunting을 참조하십시오 .

편집, Jason은 어떤 이유로 게시물을 삭제 했으므로 Object의 constructor속성을 사용하십시오.


예, 죄송합니다. instanceof ()가 더 나은 방법이라고 생각했기 때문에 삭제했지만 참조로 사용할 수 있도록 삭제를 취소했습니다.
Jason Bunting

2
다른 사람들이 비슷한 문제를 겪고 나중에 질문을 할 수 있다면 완벽한 답변보다 유용하지는 않습니다. 따라서 삭제하지 않아야합니다. 오답에 대한 삭제를 저장하십시오.
sblundy

2
그래, 나도 알아-당신은 성가대에게 설교하고 있습니다, 나는 다른 사람들에게 똑같은 것을 말했습니다. 우리가 진실로 알고있는 것들을 사는 것은 종종 보이는 것보다 어렵습니다. :)
Jason Bunting

0

누구나 jQuery로 작업하는 솔루션을 찾고 있다면 조정 된 위키 코드가 있습니다 (원본은 jQuery입니다).

Object.defineProperty(Object.prototype, "getClassName", {
    value: function() {
        var funcNameRegex = /function (.{1,})\(/;
        var results = (funcNameRegex).exec((this).constructor.toString());
        return (results && results.length > 1) ? results[1] : "";
    }
});

예, jQuery는 'hasOwnProperty'확인을 수행하지 못하므로를 열거합니다 getName.
nicodemus13

0

Lodash에는 많은 isMethod가 있으므로 Lodash를 사용하는 경우 다음과 같은 믹스 인이 유용 할 수 있습니다.

  // Mixin for identifying a Javascript Object

  _.mixin({
      'identify' : function(object) {
        var output;
          var isMethods = ['isArguments', 'isArray', 'isArguments', 'isBoolean', 'isDate', 'isArguments', 
              'isElement', 'isError', 'isFunction', 'isNaN', 'isNull', 'isNumber', 
              'isPlainObject', 'isRegExp', 'isString', 'isTypedArray', 'isUndefined', 'isEmpty', 'isObject']

          this.each(isMethods, function (method) {
              if (this[method](object)) {
                output = method;
                return false;
              }
          }.bind(this));
      return output;
      }
  });

loident에 "identify"라는 메소드를 추가하면 다음과 같이 작동합니다.

console.log(_.identify('hello friend'));       // isString

플 런커 : http://plnkr.co/edit/Zdr0KDtQt76Ul3KTEDSN


0

좋아, 사람들 나는 천천히 몇 년 동안 이것을 위해 모든 방법을 잡기 위해 천천히 롤을 만들어 왔습니다! 비결은 다음과 같습니다.

  1. 클래스를 만드는 메커니즘이 있습니다.
  2. 기본 생성자가 생성 / 생성 한 모든 사용자 생성 클래스, 프리미티브 및 값을 확인하는 메커니즘이 있습니다.
  3. 위의 기능이 코드 / 응용 프로그램 / 라이브러리 등을 통해 침투 할 수 있도록 사용자가 만든 클래스를 새로운 클래스로 확장하는 메커니즘을 갖추십시오.

예를 들어 (또는 문제를 처리 한 방법을 보려면) github에서 다음 코드를 확인하십시오 : https://github.com/elycruz/sjljs/blob/master/src/sjl/sjl.js 및 검색 :

classOf =,, classOfIs =및 (또는 defineSubClass =백틱 (`)없이).

보시다시피 기본 classOf/ 사용자 정의 클래스인지 여부, 기본 생성자, Null, NaN 등을 사용하여 생성 된 값인지 여부에 관계없이 클래스 / 생성자 유형 이름을 항상 제공 해야하는 메커니즘 이 있습니다. 모든 단일 자바 스크립트 값에 대해 classOf함수 에서 고유 유형 이름을 얻습니다 . 또한 실제 생성자를 전달 sjl.classOfIs하여 값의 유형을 확인할 수있을뿐만 아니라 값의 유형을 확인할 수 있습니다! 예를 들어 :

```// 긴 네임 스페이스를 용서해주세요! 한동안 사용하기 전까지는 그 영향에 대해 전혀 몰랐습니다.

var SomeCustomClass = sjl.package.stdlib.Extendable.extend({
    constructor: function SomeCustomClass () {},
    // ...
}),

HelloIterator = sjl.ns.stdlib.Iterator.extend( 
    function HelloIterator () {}, 
    { /* ... methods here ... */ },
    { /* ... static props/methods here ... */ }
),

helloIt = new HelloIterator();

sjl.classOfIs(new SomeCustomClass(), SomeCustomClass) === true; // `true`
sjl.classOfIs(helloIt, HelloIterator) === true; // `true`

var someString = 'helloworld';

sjl.classOfIs(someString, String) === true; // `true`

sjl.classOfIs(99, Number) === true; // true

sjl.classOf(NaN) === 'NaN'; // true

sjl.classOf(new Map()) === 'Map';
sjl.classOf(new Set()) === 'Set';
sjl.classOfIs([1, 2, 4], Array) === true; // `true`

// etc..

// Also optionally the type you want to check against could be the type's name
sjl.classOfIs(['a', 'b', 'c'], 'Array') === true; // `true`!
sjl.classOfIs(helloIt, 'HelloIterator') === true; // `true`!

```

위에서 언급 한 설정을 사용하는 방법에 대한 자세한 내용은 https://github.com/elycruz/sjljs를 참조하십시오.

주제에 관한 내용이 담긴 책들 :-Stoyan Stefanov의 "자바 스크립트 패턴". - "자바 스크립트-결정적인 가이드." 데이비드 플래너 건 -그리고 많은 다른 .. (검색 웹).

또한 신속 내가 여기에 대해 이야기하고 기능을 테스트 할 수 있습니다 : - http://sjljs.elycruz.com/0.5.18/tests/for-browser/ (또한 URL에서 0.5.18 경로는 GitHub의에서 소스를 가지고 거기에 node_modules 등을 뺀 것).

행복한 코딩!


0

상당히 간단합니다!

  • JS에서 무엇이든 유형을 얻는 가장 좋아하는 방법
function getType(entity){
    var x = Object.prototype.toString.call(entity)
    return x.split(" ")[1].split(']')[0].toLowerCase()
}
  • JS의 모든 유형을 확인하는 가장 좋아하는 방법
function checkType(entity, type){
    return getType(entity) === type
}

-1

사용하십시오 class.name. 이것은 또한 작동합니다 function.name.

class TestA {}
console.log(TestA.name); // "TestA"

function TestB() {}
console.log(TestB.name); // "TestB"

질문은 분명히 말하지만 class실례 는 아닙니다.
qwertzguy
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.