2009-01-23 23 views
55

बस उत्सुक:4 संख्या का उदाहरण क्यों नहीं है?

  • 4 instanceof संख्या => झूठी
  • नई संख्या (4) संख्या => true instanceof?

यह क्यों है? तार के साथ एक ही:

  • 'some string' instanceof String रिटर्न झूठी
  • new String('some string') instanceof String => true
  • String('some string') instanceof String भी झूठी
  • ('some string').toString instanceof String भी रिटर्न झूठी

वस्तु के लिए, सरणी या समारोह प्रकार instanceof ऑपरेटर रिटर्न अपेक्षित के रूप में काम करता है। मुझे नहीं पता कि यह कैसे समझें।

[नई अंतर्दृष्टि]

Object.prototype.is = function() { 
     var test = arguments.length ? [].slice.call(arguments) : null 
      ,self = this.constructor; 
     return test ? !!(test.filter(function(a){return a === self}).length) 
       : (this.constructor.name || 
        (String(self).match (/^function\s*([^\s(]+)/im) 
        || [0,'ANONYMOUS_CONSTRUCTOR']) [1]); 
} 
// usage 
var Newclass = function(){}; // anonymous Constructor function 
var Some = function Some(){}; // named Constructor function 
(5).is();      //=> Number 
'hello world'.is();   //=> String 
(new Newclass()).is();  //=> ANONYMOUS_CONSTRUCTOR 
(new Some()).is();   //=> Some 
/[a-z]/.is();     //=> RegExp 
'5'.is(Number);    //=> false 
'5'.is(String);    //=> true 
+0

आपको 'Number.prototype.isPrototypeOf (inp) 'का उपयोग करना होगा - यदि आपका तरीका सही तरीके से किया जाता है तो आपका तरीका भी काम करेगा:' inp.constructor === संख्या'; यह असफल हो सकता है, क्योंकि 'कन्स्ट्रक्टर' प्रोटोटाइप की एक संपत्ति है और इसे ओवरराइट किया जा सकता है! – Christoph

+0

मुझे यकीन नहीं है कि मैं समझता हूं कि 'ओवरराइट किया जा सकता है' के साथ आपका क्या मतलब है। इसका मतलब यह नहीं है कि मैं कुछ अन्य कन्स्ट्रक्टर के साथ कन्स्ट्रक्टर को ओवरराइट कर सकता हूं (इसे आजमाया)। Number.prototype.isPrototypeOf (4) रास्ते से झूठी रिटर्न देता है, इसलिए मैं इसका उपयोग आदिम मूल्यों के प्रकार की जांच के लिए नहीं कर सकता, क्या मैं सही हूँ? – KooiInc

+0

वह पूरा बिंदु था (आदिम! == लपेटा आदिम)! 'Obj [' constructor '] = ??? 'काम करता है क्योंकि कन्स्ट्रक्टर की जांच खतरनाक है! मैं अपने 'टाइपऑफ()' फ़ंक्शन का उपयोग करने का सुझाव दूंगा; प्राइमेटिव्स और लिपटे प्राइमेटिव्स का इलाज करने के लिए, 'if (typeOf (x) .toLowerCase() ===' string ')' – Christoph

उत्तर

57

value instanceof ConstructorConstructor.prototype.isPrototypeOf(value) रूप में ही है और दोनों की जाँच [[प्रोटोटाइप]] - एक विशिष्ट वस्तु की आवृत्तियां के लिए value की श्रृंखला।

स्ट्रिंग्स और संख्या आदिम मूल्य, वस्तुओं नहीं हैं और इसलिए [[प्रोटोटाइप]] नहीं है, इसलिए यह केवल तभी काम करेगा जब आप नियमित वस्तुओं (जिसे जावा में 'मुक्केबाजी' कहा जाता है) में लपेटें।

इसके अलावा, जैसा आपने देखा, String(value) और new String(value) अलग बातें करते हैं: क्या आप में निर्मित प्रकार new ऑपरेटर का उपयोग किए बिना, वे विशिष्ट प्रकार के तर्क परिवर्तित करने के लिए ('डाली') की कोशिश की निर्माता कार्यों को कॉल करते हैं । यदि आप new ऑपरेटर का उपयोग करते हैं, तो वे एक रैपर ऑब्जेक्ट बनाते हैं।

new String(value) लगभग Object(String(value)) के बराबर है, जो new Object(String(value)) जैसा व्यवहार करता है।


जावास्क्रिप्ट में प्रकार पर कुछ और: ECMA-262 को परिभाषित करता है निम्नलिखित आदिम प्रकार: अपरिभाषित, अशक्त, बूलियन, संख्या, और स्ट्रिंग। इसके अतिरिक्त, गुणों के लिए ऑब्जेक्ट प्रकार है।

उदाहरण के लिए, कार्यों प्रकार वस्तु के हैं (वे सिर्फ एक विशेष संपत्ति कहा जाता है [[कॉल]] है), और null प्रकार अशक्त की एक आदिम मूल्य है। इसका मतलब है कि typeof ऑपरेटर का परिणाम वास्तव में एक मान के प्रकार को वापस नहीं करता है ...

आमतौर पर, जावास्क्रिप्ट ऑब्जेक्ट्स में [[वर्ग]] नामक एक और संपत्ति होती है। आप इसे Object.prototype.toString.call(value) के माध्यम से प्राप्त कर सकते हैं (यह '[objectClassname]') लौटाएगा।Arrays और function ऑब्जेक्ट प्रकार हैं, लेकिन उनकी कक्षाएं ऐरे और फ़ंक्शन हैं।

instanceof विफल होने पर किसी ऑब्जेक्ट की कक्षा के लिए परीक्षण विफल रहता है (उदाहरण के लिए जब ऑब्जेक्ट विंडो/फ्रेम सीमाओं के बीच पारित होते हैं और समान प्रोटोटाइप साझा नहीं करते हैं)।


इसके अलावा, आप typeof के इस उन्नत संस्करण की जाँच करने के लिए चाहते हो सकता है: यह लोअर केस में अपने प्रकार वापस आ जाएगी

function typeOf(value) { 
    var type = typeof value; 

    switch(type) { 
     case 'object': 
     return value === null ? 'null' : Object.prototype.toString.call(value). 
      match(/^\[object (.*)\]$/)[1] 

     case 'function': 
     return 'Function'; 

     default: 
     return type; 
    } 
} 

पुरातन के लिए, वस्तुओं के लिए, यह वापस आ जाएगी उनके वर्गशीर्षक मामले में।

उदाहरण:

  • प्रकार के पुरातन लिएसंख्या (जैसे 5), यह 'number' वापस आ जाएगी, वर्गसंख्या (new Number(5) जैसे) के आवरण वस्तुओं के लिए, यह 'Number' वापस आ जाएगा;

  • कार्यों के लिए, यह 'Function' वापस करेगा।

आप आदिम मूल्यों और आवरण वस्तुओं के बीच विचार करने के लिए नहीं करना चाहते हैं (जो, शायद बुरा कारण के लिए), typeOf(...).toLowerCase() का उपयोग करें।

ज्ञात बग आईई में कुछ अंतर्निहित फ़ंक्शंस हैं, जिन्हें 'Object' माना जाता है और कुछ COM + ऑब्जेक्ट्स के साथ उपयोग किए जाने पर 'unknown' का वापसी मान माना जाता है।

+0

@annakata: ECMA-262 जांचें। प्रकार को अपरिभाषित, शून्य, बूलियन, संख्या, स्ट्रिंग और ऑब्जेक्ट कहा जाता है; इससे कोई फर्क नहीं पड़ता कि 'टाइपोफ' रिटर्न क्या है ... – Christoph

+0

@ क्रिस्टोफ - रैपर ऑब्जेक्ट्स अपरकेस के बाद से यह बहुत मायने रखता है, और टाइपफॉर्म्स लोअरकेस हैं और कुछ और भी सुलभ नहीं है। इसलिए सम्मेलन और अभ्यास लोअरकेस में डेटाटाइप को संदर्भित करता है जैसा कि यहां स्पष्ट किया गया है: https://developer.mozilla.org/En/JS/Glossary – annakata

+0

@annakata: 'typeof' टूटा हुआ है - इसके वापसी मूल्य में कुछ भी नहीं है वास्तविक प्रकार के साथ करो! – Christoph

12

आप का मूल्यांकन करने की कोशिश कर सकते हैं:

>>> typeof("a") 
"string" 
>>> typeof(new String("a")) 
"object" 
>>> typeof(4) 
"number" 
>>> typeof(new Number(4)) 
"object" 
1

यह जो मैंने पाया कुछ बाहर फैल जाती है जावास्क्रिप्ट का एक अति सूक्ष्म अंतर है। एलएचएस object प्रकार नहीं है, तो instanceof ऑपरेटर का हमेशा झूठा परिणाम होगा।

ध्यान दें कि new String('Hello World') का परिणाम string प्रकार नहीं है लेकिन object है। new ऑपरेटर हमेशा एक ऑब्जेक्ट में परिणाम देता है। मैं बात की इस तरह देखें: -

function fnX(value) 
{ 
    if (typeof value == 'string') 
    { 
      \\Do stuff 
    } 
} 
fnX(new String('Hello World')); 

उम्मीद है कि "Do Stuff" क्या होगा, लेकिन यह क्योंकि मूल्य typeof वस्तु है नहीं करता है।

2

जैसा कि क्रिस्टोफ के उत्तर में बताया गया है, स्ट्रिंग और संख्या अक्षर स्ट्रिंग और संख्या ऑब्जेक्ट्स के समान नहीं हैं।आप शाब्दिक पर स्ट्रिंग या संख्या से किसी भी विधि का उपयोग करते हैं, कहते हैं कि

'a string literal'.length 

शाब्दिक अस्थायी रूप से एक वस्तु में बदल जाती है, विधि शुरू हो जाती है और वस्तु खारिज कर दिया है।
साहित्य वस्तुओं पर कुछ अलग फायदे हैं।

//false, two different objects with the same value 
alert(new String('string') == new String('string')); 

//true, identical literals 
alert('string' == 'string'); 

अप्रत्याशित व्यवहार से बचने के लिए हमेशा शाब्दिक उपयोग करें!
आप टाइपकास्ट करने के लिए संख्या() और स्ट्रिंग() का उपयोग कर सकते है अगर आप की जरूरत है:

//true 
alert(Number('5') === 5) 

//false 
alert('5' === 5) 
0

आदिम संख्या के मामले में, isNaN विधि यह भी आप कर सकते हैं।

संबंधित मुद्दे