JS 객체의 유형을 확인하는 가장 정확한 방법은 무엇입니까?


137

typeof운영자는 정말 개체의 실제 유형을 발견하는 데 도움이되지 않습니다.

이미 다음 코드를 보았습니다.

Object.prototype.toString.apply(t)  

질문:

객체 유형을 확인 하는 가장 정확한 방법입니까?





3
가장 정확한 방법은 유형을 테스트하지 않는 것입니다. 왜 유형이 필요합니까?
hugomg

Object.prototype.toString.call / Object.prototype.toString.apply
xgqfrms

답변:


191

JavaScript 사양은 객체의 클래스를 결정하는 올바른 방법을 정확히 제공합니다.

Object.prototype.toString.call(t);

http://bonsaiden.github.com/JavaScript-Garden/#types


5
특정 유형을 찾고 있다면 다음 줄을 따라 무언가 Object.prototype.toString.call(new FormData()) === "[object FormData]"를 원할 것입니다. 당신은 또한 사용할 수 있습니다 slice(8, -1)반환하는 FormData대신[object FormData]
크리스 Marisic

4
사용 Object.prototype{}?에 차이가 있습니까?
GetFree

3
어쩌면 이것이 수년에 걸쳐 바뀌었지만 Object.prototype.toString.call(new MyCustomObject())돌아 오는 [object Object]반면 new MyCustomObject() instanceOf MyCustomObject returns true내가 원하는 것은 (Chrome 54.0.2840.99 m)
Maslow

@Maslow, 당신이 제기 한 것과 같은 문제가 발생했습니다. 온라인으로 일부 문서를 살펴본 후을 사용했습니다 new MyCustomObject().constructor === MyCustomObject.
solstice333

3
이 코드를 더 편리한 방법으로 래핑하지 않았거나 추가 연산자가이를 컴파일 할 수없는 이유는 무엇입니까? 나는 당신이 메신저 일 뿐이라는 것을 알고 있지만 솔직히 그것은 끔찍합니다.
Andrew S

60

Object.prototype.toString좋은 방법이지만, 성능은 최악이다.

http://jsperf.com/check-js-type

js 유형 성능 확인

사용하여 typeof몇 가지 기본적인 문제 (문자열, 숫자, 부울 ...) 사용을 해결하기 위해 Object.prototype.toString(배열, 날짜, 정규식 등) 복잡한 무언가를 해결하기 위해.

그리고 이것은 내 해결책입니다.

var type = (function(global) {
    var cache = {};
    return function(obj) {
        var key;
        return obj === null ? 'null' // null
            : obj === global ? 'global' // window in browser or global in nodejs
            : (key = typeof obj) !== 'object' ? key // basic: string, boolean, number, undefined, function
            : obj.nodeType ? 'object' // DOM element
            : cache[key = ({}).toString.call(obj)] // cached. date, regexp, error, object, array, math
            || (cache[key] = key.slice(8, -1).toLowerCase()); // get XXXX from [object XXXX], and cache it
    };
}(this));

로 사용:

type(function(){}); // -> "function"
type([1, 2, 3]); // -> "array"
type(new Date()); // -> "date"
type({}); // -> "object"

jsPerf에 대한 테스트는 정확하지 않습니다. 이러한 테스트는 동일하지 않습니다 (동일한 테스트). 예를 들어 typeof []는 "object"를 반환하고 typeof {}은 하나는 객체 Array이고 다른 하나는 객체 Object 인 경우에도 "object"를 반환합니다. 이 테스트에는 다른 많은 문제가 있습니다. jsPerf를 살펴볼 때 테스트에서 Apple과 Apple을 비교하는 것을주의하십시오.
kmatheny

귀하의 type기능은 훌륭하지만 다른 type기능 과 비교하여 어떻게 작동하는지 살펴보십시오 . http://jsperf.com/code-type-test-a-test
Progo

18
이러한 성능 지표는 상식적으로 강화되어야합니다. 물론, prototype.toString은 다른 것보다 훨씬 느리지 만, 웅장한 방식에서는 호출 당 평균 수백 나노초 가 걸립니다 . 이 호출이 매우 자주 실행되는 중요한 경로에서 사용되지 않는 한 이것은 무해합니다. 오히려 1 마이크로 초 더 빨리 끝나는 코드보다 직선 코드가 필요합니다.
David

({}).toString.call(obj)Object.prototype.toString jsperf.com/object-check-test77
timaschew

좋은 해결책. 나는 당신의 함수를 내 라이브러리로 빌린다. :)
Dong Nguyen

19

허용 된 답변은 정확하지만 빌드하는 대부분의 프로젝트 에서이 작은 유틸리티를 정의하고 싶습니다.

var types = {
   'get': function(prop) {
      return Object.prototype.toString.call(prop);
   },
   'null': '[object Null]',
   'object': '[object Object]',
   'array': '[object Array]',
   'string': '[object String]',
   'boolean': '[object Boolean]',
   'number': '[object Number]',
   'date': '[object Date]',
}

이런 식으로 사용 :

if(types.get(prop) == types.number) {

}

각도를 사용하는 경우 깨끗하게 주입 할 수도 있습니다.

angular.constant('types', types);

11
var o = ...
var proto =  Object.getPrototypeOf(o);
proto === SomeThing;

객체가 가질 것으로 예상되는 프로토 타입을 처리 한 다음 비교하십시오.

예를 들어

var o = "someString";
var proto =  Object.getPrototypeOf(o);
proto === String.prototype; // true

이것이 말하는 것보다 어떻게 더 좋거나 다른가 o instanceof String; //true?
Jamie Treworgy

@jamietre "foo" instanceof String는 휴식 때문에
Raynos

"typeof (o) === 'object'&& o instanceof SomeObject"입니다. 문자열을 쉽게 테스트 할 수 있습니다. 테스트 대상을 미리 알아야하는 기본적인 문제를 해결하지 않고 추가 작업처럼 보입니다.
Jamie Treworgy

코드 스 니펫은 말이되지 않지만 죄송합니다 typeof(x)==='string'. 문자열을 테스트하는 경우 대신 사용하십시오.
Jamie Treworgy

BTW는 Object.getPrototypeOf(true)에서를 (true).constructor반환합니다 Boolean.
katspaugh

5

나는 여기에 표시된 대부분의 솔루션이 과도하게 엔지니어링되어 어려움을 겪고 있다고 주장합니다. 값이 유형인지 확인하는 가장 간단한 방법은 아마도 그 속성에 [object Object]대해 확인 .constructor하는 것입니다.

function isObject (a) { return a != null && a.constructor === Object; }

또는 화살표 기능으로 더 짧습니다.

const isObject = a => a != null && a.constructor === Object;

a != null하나가 전달 수 있기 때문에 일부는 필요하다 null또는 undefined당신이 중 하나에서 생성자 속성을 추출 할 수 없습니다.

다음을 통해 생성 된 모든 객체와 작동합니다.

  • Object생성자
  • 리터럴 {}

그것의 또 다른 멋진 기능은를 사용하는 사용자 정의 클래스에 대한 올바른 보고서를 제공 할 수 있다는 것입니다 Symbol.toStringTag. 예를 들면 다음과 같습니다.

class MimicObject {
  get [Symbol.toStringTag]() {
    return 'Object';
  }
}

여기서 문제 Object.prototype.toString는 인스턴스를 호출 할 때 잘못된 보고서 [object Object]가 반환된다는 것입니다.

let fakeObj = new MimicObject();
Object.prototype.toString.call(fakeObj); // -> [object Object]

그러나 생성자를 검사하면 올바른 결과가 나타납니다.

let fakeObj = new MimicObject();
fakeObj.constructor === Object; // -> false

4

객체의 REAL 유형 (기본 객체 또는 DataType 이름 (예 : String, Date, Number, .. 등)과 객체의 REAL 유형 (사용자 정의 이름 포함)을 모두 찾는 가장 좋은 방법은 잡아내는 것입니다. 객체 프로토 타입 생성자의 이름 속성 :

기본 유형 Ex1 :

var string1 = "Test";
console.log(string1.__proto__.constructor.name);

표시합니다 :

String

예 2 :

var array1 = [];
console.log(array1.__proto__.constructor.name);

표시합니다 :

Array

커스텀 클래스 :

function CustomClass(){
  console.log("Custom Class Object Created!");
}
var custom1 = new CustomClass();

console.log(custom1.__proto__.constructor.name);

표시합니다 :

CustomClass

객체가 null또는 이면 실패합니다 undefined.
율리우스 기사

2

내가 아는 오래된 질문. 변환 할 필요가 없습니다. 이 기능을 참조하십시오 :

function getType( oObj )
{
    if( typeof oObj === "object" )
    {
          return ( oObj === null )?'Null':
          // Check if it is an alien object, for example created as {world:'hello'}
          ( typeof oObj.constructor !== "function" )?'Object':
          // else return object name (string)
          oObj.constructor.name;              
    }   

    // Test simple types (not constructed types)
    return ( typeof oObj === "boolean")?'Boolean':
           ( typeof oObj === "number")?'Number':
           ( typeof oObj === "string")?'String':
           ( typeof oObj === "function")?'Function':false;

}; 

예 :

function MyObject() {}; // Just for example

console.log( getType( new String( "hello ") )); // String
console.log( getType( new Function() );         // Function
console.log( getType( {} ));                    // Object
console.log( getType( [] ));                    // Array
console.log( getType( new MyObject() ));        // MyObject

var bTest = false,
    uAny,  // Is undefined
    fTest  function() {};

 // Non constructed standard types
console.log( getType( bTest ));                 // Boolean
console.log( getType( 1.00 ));                  // Number
console.log( getType( 2000 ));                  // Number
console.log( getType( 'hello' ));               // String
console.log( getType( "hello" ));               // String
console.log( getType( fTest ));                 // Function
console.log( getType( uAny ));                  // false, cannot produce
                                                // a string

저렴하고 간단합니다.


false테스트 객체가 다음 null과 같은 경우 반환undefined
Julian Knight

또는 true또는false
줄리안 나이트

@JulianKnight false는 null이거나 정의되지 않았으므로 아무 것도 유용하지 않습니다. 그래서 요점이 뭐야?
코드 비트

예제는 일치하지 않는 데이터를 반환합니다. 일부 결과는 데이터 유형이고 다른 결과는 값 false입니다. 이것이 어떻게 질문에 대답하는 데 도움이됩니까?
줄리안 기사

1
@JulianKnight 변경 사항을 보시겠습니까? 결과적으로 undefined 또는 "undefined"를 선호하는 경우 원하는 경우 마지막 false를 바꿀 수 있습니다.
코드 비트

0

위의 정답에서 영감을 얻은 작은 유형 검사 유틸리티를 구성했습니다.

thetypeof = function(name) {
        let obj = {};
        obj.object = 'object Object'
        obj.array = 'object Array'
        obj.string = 'object String'
        obj.boolean = 'object Boolean'
        obj.number = 'object Number'
        obj.type = Object.prototype.toString.call(name).slice(1, -1)
        obj.name = Object.prototype.toString.call(name).slice(8, -1)
        obj.is = (ofType) => {
            ofType = ofType.toLowerCase();
            return (obj.type === obj[ofType])? true: false
        }
        obj.isnt = (ofType) => {
            ofType = ofType.toLowerCase();
            return (obj.type !== obj[ofType])? true: false
        }
        obj.error = (ofType) => {
            throw new TypeError(`The type of ${name} is ${obj.name}: `
            +`it should be of type ${ofType}`)
        }
        return obj;
    };

예:

if (thetypeof(prop).isnt('String')) thetypeof(prop).error('String')
if (thetypeof(prop).is('Number')) // do something

있는 개체에 대한 작동하지 않는 것 null또는 undefined또는 true또는false
줄리안 나이트
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.