जेएस ऑब्जेक्ट के प्रकार की जांच करने का सबसे सटीक तरीका है?


137

typeofऑपरेटर वास्तव में एक वस्तु की वास्तविक प्रकार खोजने के लिए हमें मदद नहीं करता है।

मैंने पहले ही निम्नलिखित कोड देखा है:

Object.prototype.toString.apply(t)  

सवाल:

क्या यह वस्तु के प्रकार की जांच करने का सबसे सटीक तरीका है?


2
इस लेख पर एक नज़र डालें: javascriptweblog.wordpress.com/2011/08/08/…
जेम्स एलार्डिस

4
इस पोस्ट को देखें: stackoverflow.com/questions/332422/…
isJustMe


3
सबसे सटीक तरीका है ... प्रकार का परीक्षण नहीं करना। आपको प्रकारों की आवश्यकता क्यों है?
18

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

जवाबों:


191

जावास्क्रिप्ट विनिर्देश किसी वस्तु के वर्ग को निर्धारित करने का एक उचित तरीका देता है:

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]
क्रिस मैरिसिक

4
क्या उपयोग करने Object.prototypeऔर के बीच कोई अंतर है {}?
GetFree

3
शायद यह पिछले कुछ वर्षों में बदल गया है, लेकिन Object.prototype.toString.call(new MyCustomObject())रिटर्न [object Object]जबकि new MyCustomObject() instanceOf MyCustomObject returns trueजो कि मैं क्या (क्रोम 54.0.2840.99 मी) चाहता था है
मस्लोव

@ मैस्लो, मैं उसी मुद्दे में भाग गया हूं जिसे आपने उठाया था। ऑनलाइन कुछ दस्तावेज देखने के बाद, मैंने उपयोग करना समाप्त कर दिया new MyCustomObject().constructor === MyCustomObject
solstice333

3
यह सवाल है कि, उन्होंने इस कोड को अधिक सुविधाजनक तरीके से क्यों नहीं लपेटा है, या इसके लिए एक अतिरिक्त ऑपरेटर को संकलित करने की अनुमति दी है। मुझे पता है कि आप केवल संदेशवाहक हैं, लेकिन काफी स्पष्ट रूप से यह भयानक है।
एंड्रयू एस

60

Object.prototype.toStringएक अच्छा तरीका है, लेकिन इसके प्रदर्शन सबसे खराब है।

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

check js type प्रदर्शन

typeofकुछ बुनियादी समस्या को हल करने के लिए उपयोग करें (स्ट्रिंग, संख्या, बूलियन ...) और Object.prototype.toStringकुछ जटिल (जैसे एरे, दिनांक, RegExp) को हल करने के लिए उपयोग करें।

और यह मेरा समाधान है:

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 पर यह परीक्षण काफी सटीक नहीं है। वे परीक्षण समान नहीं हैं (एक ही चीज़ के लिए परीक्षण)। जैसे, टाइपोफ़ [] "ऑब्जेक्ट" लौटाता है, टाइपो {} भी "ऑब्जेक्ट" लौटाता है, भले ही एक ऑब्जेक्ट एरे हो और दूसरा ऑब्जेक्ट ऑब्जेक्ट हो। उस परीक्षण के साथ कई अन्य समस्याएं हैं ... jsPerf को देखते समय सावधान रहें कि परीक्षण सेब से सेब की तुलना कर रहे हैं।
किमीथैनी

आपका typeकार्य अच्छा है, लेकिन यह देखें कि यह कुछ अन्य typeकार्यों की तुलना में कैसा है । http://jsperf.com/code-type-test-a-test
प्रोगो

18
इन प्रदर्शन मेट्रिक्स को कुछ सामान्य ज्ञान के साथ सम्‍मिलित होना चाहिए। निश्चित रूप से, प्रोटोटाइप .toString परिमाण के एक क्रम के द्वारा दूसरों की तुलना में धीमा है, लेकिन चीजों की भव्य योजना में यह औसतन प्रति युगल सौ नैनोसेकेंड लेता है । जब तक इस कॉल का उपयोग एक महत्वपूर्ण पथ में किया जा रहा है जो बहुत बार निष्पादित होता है, यह संभवतः हानिरहित है। मुझे कोड के बजाय सीधे फॉरवर्ड कोड चाहिए जो एक माइक्रोसेकंड को तेजी से खत्म करता है।
डेविड

({}).toString.call(obj)Object.prototype.toString jsperf.com/object-check-test77
टाइमशेव

अच्छा समाधान। मैं आपके कार्य को अपने परिवाद में उधार लेता हूँ :)
डोंग गुयेन

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?
जेमी ट्रेवेरी

@ जमैट्रे क्योंकि "foo" instanceof Stringटूट जाता है
रेयोनोस

ठीक है, इसलिए "टाइपोफ़ (ओ) === 'ऑब्जेक्ट' और & quot; ओ ओफ़ोफ़ एफ़ऑब्जेक्ट"। स्ट्रिंग्स के लिए परीक्षण करना आसान है। बस अतिरिक्त काम की तरह लगता है, पहले से जानने के लिए कि आप क्या परीक्षण कर रहे हैं, की मूल समस्या को हल किए बिना।
जेमी ट्रेवरजी

क्षमा करें कि कोड स्निपेट का कोई मतलब नहीं है, लेकिन मुझे लगता है कि आप जानते हैं कि मेरा क्या मतलब है, यदि आप स्ट्रिंग्स के लिए परीक्षण कर रहे हैं, तो typeof(x)==='string'इसके बजाय उपयोग करें ।
जेमी ट्रूवेरी

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

किसी ऑब्जेक्ट का वास्तविक प्रकार (BOTH सहित देशी ऑब्जेक्ट या डेटाटाइप नाम (जैसे स्ट्रिंग, दिनांक, संख्या, ..etc) और REAL प्रकार की ऑब्जेक्ट (यहां तक ​​कि कस्टम वाले) का पता लगाने का सबसे अच्छा तरीका है; ऑब्जेक्ट प्रोटोटाइप के निर्माता की नाम संपत्ति:

देशी प्रकार Ex1:

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

प्रदर्शित करता है:

String

Ex2:

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
जूलियन नाइट

या trueयाfalse
जूलियन नाइट

@JulianKnight झूठी, अशक्त या अपरिभाषित पर ठीक है, यह कुछ भी उपयोगी नहीं है। तो फिर विषय बिंदु क्या है?
संहिता

आपका उदाहरण असंगत डेटा देता है। कुछ परिणाम डेटा प्रकार हैं और अन्य मूल्य हैं false। यह प्रश्न का उत्तर देने में कैसे मदद करता है?
जूलियन नाइट

1
@JulianKnight परिवर्तन देखें, यह है कि आप क्या चाहते हैं? यदि आप परिणाम के रूप में अपरिभाषित या "अपरिभाषित" पसंद करते हैं, तो यदि आप चाहें तो अंतिम गलत की जगह ले सकते हैं।
कोडबीट

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
जूलियन नाइट
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.