[javascript] 객체 타입의 이름을 얻는다

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



답변

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유용한 부분을 ​​이해하는 것이 중요하지만 현재는이 토론과 관련이 있다고 생각하지 않습니다. 그래도 마음이 바뀌어 열려 있습니다. 🙂


답변

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

<<Object instance>>.constructor.name

예를 들어, 다음 코드에서

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

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


답변

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

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

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


답변

최신 정보

정확히 말하면 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


답변

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


답변

다음은 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를 반환한다는 것입니다.


답변

나는 실제로 비슷한 것을 찾고 있었고이 질문을 보았습니다. 다음은 유형을 얻는 방법입니다. 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);
}