2011-12-27 9 views
8

मैं एक जावास्क्रिप्ट स्टैकट्रैक लाइब्रेरी लिख रहा हूं। लाइब्रेरी को गीलेर का पता लगाने की ज़रूरत है, किसी विशेष ऑब्जेक्ट या फ़ंक्शन प्रोग्रामर द्वारा बनाया गया था या पर्यावरण के हिस्से के रूप में था (अंतर्निहित वस्तुओं सहित)। होस्ट ऑब्जेक्ट्स उनके अप्रत्याशित व्यवहार के कारण थोड़ा समस्याग्रस्त हो रहे हैं, इसलिए मैं यह निर्धारित करने के लिए पर्यावरण-अज्ञेय तरीके से हूं कि जावास्क्रिप्ट में कोई विशेष ऑब्जेक्ट होस्ट ऑब्जेक्ट है (ECMAScript 3 - 4.3.8 देखें)। हालांकि, देशी वस्तुओं और आदिम मूल्यों से होस्ट ऑब्जेक्ट्स को अलग करना विशेष रूप से ब्राउज़र-कम वातावरण में प्रोग्रामर के लिए उपयोगी है, इसलिए मैं उस पर ध्यान केंद्रित करना चाहता हूं, बजाय मेरी लाइब्रेरी में या ऑब्जेक्टिंग प्रोग्रामर पर होस्ट ऑब्जेक्ट्स की समस्याएं -निर्मित वस्तुओं।जावास्क्रिप्ट होस्ट ऑब्जेक्ट्स का पता लगाने के लिए कोई पर्यावरण-अज्ञात तरीका है?

अभी तक मैं केवल समाधान के साथ आने में सक्षम हूं जो पर्यावरण जावास्क्रिप्ट कोड पर निर्भर करता है। उदाहरण के लिए:

// IE Only: does not implement valueOf() in Host Objects 
var isHost = (typeof obj === 'object' && typeof obj.valueOf === 'undefined'); 

// Firefox Only: Host objects have own constructor 
var isHost = (obj.constructor && obj.hasOwnProperty('constructor')); 

मैंने देखा है कि jQuery के अपने isPlainObject() विधि को भी पर्यावरण पर निर्भर है, और तर्क नहीं बल्कि जटिल है।

शायद ऐसा इसलिए है क्योंकि मेजबान वस्तुओं के साथ जानवर की प्रकृति (क्योंकि उनका व्यवहार पर्यावरण द्वारा परिभाषित किया गया है), लेकिन मैं यह देखने के लिए कुछ और खोदना चाहता हूं कि यह संभव है या नहीं और सोच रहा था कि कोई चला गया है इस विशेष समस्या से पहले और एक समाधान तैयार है।

तो। क्या किसी को मेजबान ऑब्जेक्ट्स के परीक्षण के लिए एक सरल मंच-स्वतंत्र समाधान पता है? और यदि यह ब्राउज़र-कम वातावरण जैसे नोड या राइनो में चलता है तो इसके लिए बेहतर होता है।

संभावित दृष्टिकोण (जो काम नहीं कर सकते हैं):

  • मेजबान वस्तुओं की विशेषताओं के लिए परीक्षण एक खो कारण की तरह लगता है, यह देखते हुए उनके व्यवहार के लिए कोई विनिर्देश है कि वहाँ है, तथापि परीक्षण है कि क्या वस्तु का हिस्सा है ईएस 3 विनिर्देश एक संभावना हो सकती है।
  • मैं का उपयोग कर की कोशिश की है Object.prototype.toString() यह देखते हुए कि काफी विशेष रूप से अपनी परिभाषित है, लेकिन के रूप में कुछ वातावरण (अर्थात् आईई) देशी और मेजबान वस्तुओं के लिए समान मान के लिए चुन परिणाम अनिर्णायक हैं।
  • यह देखना हो प्रोटोटाइप श्रृंखला के माध्यम से एक वस्तु का परम constructor वास्तव में एक instanceof Function है द्वारा ऐसा करना संभव हो सकता है।
+7

आप जिस समस्या को हल करने की कोशिश कर रहे हैं? –

+1

मुझे पूरा यकीन है कि यह सभी वातावरण में काम नहीं करता है, लेकिन आप 'Object.prototype.toString.call (obj) 'को आजमा सकते हैं और देख सकते हैं कि आपको' [ऑब्जेक्ट ऑब्जेक्ट]' मिलता है (जो कि सादे ऑब्जेक्ट्स/उदाहरण हैं उपज) या कुछ ऐसा निर्धारित करने के लिए '[ऑब्जेक्ट HTMLBodyElement] 'जैसे कुछ होस्ट ऑब्जेक्ट है। – pimvdb

+0

@ कैमिलो मार्टिन, मैं जावास्क्रिप्ट स्टैकट्रस लाइब्रेरी पर काम कर रहा हूं, मेजबान ऑब्जेक्ट्स उनके अप्रत्याशित व्यवहार के कारण थोड़ा समस्याग्रस्त हो रहे हैं, इसलिए उन्हें चारों ओर कोड करना होगा। हालांकि यहां अन्य समाधानों में विशेष रूप से ब्राउज़र-कम वातावरण में प्रोग्रामर के लिए समाधान उपयोगी है। –

उत्तर

0

मेरा मानना ​​है कि होस्ट ऑब्जेक्ट्स की प्रकृति का मतलब है कि उन्हें पहचानने के लिए एक सरल, पर्यावरण-अज्ञात तरीका नहीं है। यदि आप उत्सुक हैं, तो अधिक के लिए this discussion on SO देखें।

जैसा कि आपने ध्यान दिया है, jQuery प्रोजेक्ट में भी tried to detect host objects है और इसी तरह की परेशानी में भाग लेता है। उस बग पेज पर चर्चा बहुत कह रही है।

+0

jQuery सिर्फ jQuery है, जितना अधिक उनके कोड कई तरीकों से स्मार्ट है, यह अभी भी दायरे में सीमित है और इसके विशेष उद्देश्य (ब्राउज़र में डोम मैनिपुलेशन) के लिए विशिष्ट है। –

+0

एसओ लिंक मरने लगता है – the8472

0

मुझे एक ऐसा विचार है जो सभी संदर्भों में लागू नहीं हो सकता है।

सुनिश्चित करें कि आपके स्क्रिप्ट पहले एक है निष्पादित करने के लिए, और एक बंद में लपेट, बहुत पसंद जे एस चौखटे करना सुनिश्चित करें।
फिर, अपने वैश्विक विस्तार में सभी वस्तुओं के माध्यम से लूप (एक ब्राउज़र, window अपरिभाषित हो जाएगा नहीं है आप कुछ पर हैं कि, इसलिए स्क्रिप्ट की शुरुआत में एक window = this करते हैं), और अपने बच्चों के माध्यम से लूप, और तो पर।आपकी इच्छाओं को छोड़कर सभी ऑब्जेक्ट होस्ट ऑब्जेक्ट्स होंगे! फिर आप इसे स्थानीय डेटाबेस में जोड़ सकते हैं या इसे स्टोर भी कर सकते हैं और इसे भविष्य के उपयोग के लिए चल रहे वातावरण से जोड़ सकते हैं।

+0

कोशिश की, काम नहीं करता है, कुछ होस्ट ऑब्जेक्ट्स स्वयं के बराबर नहीं हैं, इसलिए एक ही होस्ट ऑब्जेक्ट के दो संदर्भों के बीच बराबर तुलना का परिणाम अप्रत्याशित है। –

+0

यह बहुत बुरा है। लेकिन, ये कौन थे? मैं उत्सुक हूँ। आईई में –

+0

विंडो.फ्रेम सबसे खराब है। console.log (फ्रेम === फ्रेम) आज़माएं; –

5

जब आप definition of host object - "ईसीएमएस्क्रिप्ट के निष्पादन वातावरण को पूरा करने के लिए होस्ट वातावरण द्वारा प्रदान की गई वस्तु को देखते हैं।" - यह स्पष्ट हो जाता है कि यह निर्धारित करने का कोई आसान तरीका नहीं है कि कोई ऑब्जेक्ट होस्ट या मूल है या नहीं।

देशी वस्तुओं के विपरीत, होस्ट ऑब्जेक्ट्स आंतरिक गुणों (जैसे [[प्रोटोटाइप]], [[कक्षा]], आदि को कार्यान्वित-विशिष्ट तरीके से परिभाषित करते हैं। ऐसा इसलिए है क्योंकि specification allows them to do this। हालांकि, कार्यान्वयन-विशिष्ट तरीके से आंतरिक व्यवहार को लागू करने के लिए मेजबान वस्तुओं के लिए "जरूरी" आवश्यकता नहीं है; यह एक "मई" आवश्यकता की आवश्यकता है। तो हम इस पर भरोसा नहीं कर सकते हैं। ये वस्तुएं "अजीब" कार्य कर सकती हैं या नहीं। बताने का कोई तरीका नहीं है।

अतीत में होस्ट ऑब्जेक्ट्स का पता लगाने के कुछ प्रयास किए गए हैं, लेकिन उनमें से सभी निश्चित रूप से कुछ वातावरण के निरीक्षणों पर भरोसा करते हैं (एमएसएचटीएम डोम उनमें से एक है) - याद रखें कि होस्ट ऑब्जेक्ट्स में कोई अद्वितीय पैटर्न नहीं है/पहचान करने के लिए विशेषता। पीटर मिचॉक्स documented most of the inferences here ("मेजबान ऑब्जेक्ट परीक्षण फ़ीचर" अनुभाग पर एक नज़र डालें)। कुख्यात typeof ... == "unknown" एमएसएचटीएम डीओएम और इसकी ActiveX- आधारित होस्ट ऑब्जेक्ट्स से आता है। नोट पीटर मुख्य रूप से ब्राउज़र पटकथा के संदर्भ में मेजबान वस्तुओं के बारे में बात करती है कि, और वह करने के लिए नीचे की जाँच करता सीमित कर देता है "इस एक मेजबान तरीका है?", आदि

कुछ वातावरण में "इस एक मेजबान संग्रह वस्तु है" होस्ट ऑब्जेक्ट्स Object.prototype (इसके खिलाफ जांचना आसान बनाता है) से प्राप्त नहीं होते हैं, या कुछ गुण हैं जो त्रुटियों को फेंक देते हैं (उदाहरण के लिए आईई में कुछ "इंटरफ़ेस" ऑब्जेक्ट्स पर "प्रोटोटाइप"), या यहां तक ​​कि स्वयं को त्रुटियों पर फेंक देते हैं।

ऐसा लगता है कि आप यह जांच सकते हैं कि कोई ऑब्जेक्ट विनिर्देश में परिभाषित लोगों में से एक है, और यदि नहीं, तो इसे होस्ट के रूप में समझा जाए। लेकिन वह वास्तव में मदद नहीं करेगा; यह केवल आपको ऑब्जेक्ट्स देगा जो में अंतर्निहित नहीं हैं। इनमें से कुछ गैर-मानक वस्तुएं अभी भी मूल हो सकती हैं (जिसका अर्थ है कि वे विनिर्देशन में वर्णित सामान्य अर्थशास्त्र लागू करेंगे)।

आपकी सर्वश्रेष्ठ शर्त आपके ऐप/स्क्रिप्ट के विशेष व्यवहार के लिए परीक्षण होगी, जो होस्ट ऑब्जेक्ट्स संवेदनशील हो सकती है। यह हमेशा सबसे सुरक्षित तरीका है। क्या आप किसी ऑब्जेक्ट से कुछ एक्सेस करने की योजना बना रहे हैं? ऑब्जेक्ट से कुछ हटाएं? ऑब्जेक्ट में कुछ जोड़ें? इसके लिए परीक्षण करें। देखें कि यह काम करता है या नहीं। यदि ऐसा नहीं होता है - तो आप होस्ट ऑब्जेक्ट से निपटने की संभावना रखते हैं।

+0

हाय @ कंगैक्स, जबकि मैं आपके अधिकांश उत्तर से सहमत हूं, ईसीएमएस्क्रिप्ट स्पेक यह भी बताता है कि * 'कोई भी वस्तु जो मूल नहीं है वह एक मेजबान वस्तु है।' *, इसलिए यह जांच कर मेजबान वस्तुओं के परीक्षण के लिए सैद्धांतिक रूप से संभव है * नहीं * मूल (जैसा कि spec में परिभाषित किया गया है)। यहां की चाल यह है कि यह जांचने के लिए कि वास्तव में एक वस्तु * मूल है, क्योंकि पर्यावरण अपने मेजबान वस्तुओं में इस व्यवहार को अधिक से अधिक जटिल बनाकर कठिन बना सकता है। –

2

लगभग सुलझ

लगभग इस काम करने के लिए पाने में कामयाब रहे।

उस होस्ट ऑब्जेक्ट्स में समाधान कम हो जाता है जो कभी-कभी मूल लोगों से अलग नहीं होता है। क्रोम पर isNative(window.alert) का परीक्षण करते समय नीचे दिया गया कोड विफल रहता है क्योंकि वेबकिट इंजन alert फ़ंक्शन को परिभाषित करता है (अब तक) किसी मूल के समान दिखता है।

यह ईएस 3 के अनुसार सादे जावास्क्रिप्ट का उपयोग करता है और परीक्षण पर आधारित है कि एक वस्तु मूल है (होस्ट ऑब्जेक्ट के विपरीत)। हालांकि, होस्ट ऑब्जेक्ट्स की ES3 परिभाषा के अनुसार: 'कोई भी वस्तु जो मूल नहीं है वह होस्ट ऑब्जेक्ट है।' होस्ट फ़ंक्शन का पता लगाने के लिए इस फ़ंक्शन का उपयोग किया जा सकता है।

// ISNATIVE OBJECT DETECTION 

function isNative(obj) { 

    switch(typeof obj) { 
     case 'number': case 'string': case 'boolean': 
      // Primitive types are not native objects 
      return false; 
    } 

    // Should be an instance of an Object 
    if (!(obj instanceof Object)) return false; 

    // Should have a constructor that is an instance of Function 
    if (typeof obj.constructor === 'undefined') return false; 
    if (!(obj.constructor instanceof Function)) return false; 

    return true; 
} 

// CHECK IF AN OBJECT IS HOST OR NATIVE 

if (typeof myObject === 'object' || typeof myObject === 'function') 
    alert(isNative(myObject) ? 'Native Object' : 'Host Object'); 

यहाँ एक list of JsFiddle tests कि IE/फ़ायरफ़ॉक्स/क्रोम में यह परीक्षण करने के लिए इस्तेमाल किया जा सकता है।

मैंने बिना किसी परेशानी के गैर-ब्राउज़र वातावरण का परीक्षण किया है, लेकिन कोड इतना बुनियादी है क्योंकि मुझे नहीं लगता कि इसमें कोई समस्या होगी।

// ASSERT HELPER FUNCTION 

var n = 0; 
function assert(condition, message) { 
    n++; 
    if (condition !== true) { 
     document.write(n + '. FAILS: ' + (message || '(no message)') + '<br/>'); 
    } else { 
     document.write(n + '. PASS: ' + (message || '(no message)') + '<br/>'); 
    } 
} 

// USER CREATED OBJECTS 

assert(isNative({}), '{} -- Plain object'); 
assert(isNative(function() {}), 'function() {} -- Plain function'); 
assert(isNative([]), '[] -- Plain array'); 

assert(isNative(/regex/), '/regex/ - Native regex'); 
assert(isNative(new Date()), 'new Date() - Native date object through instantiation'); 

assert(isNative(new String('string')), 'new String("string") - Native string object through instantiation'); 
assert(isNative(new Number(1)), 'new Number(1) - Native number object through instantiation'); 
assert(isNative(new Boolean(true)), 'new Boolean(true) - Native boolean object through instantiation'); 
assert(isNative(new Array()), 'new Array() - Native array object through instantiation'); 
assert(isNative(new Object()), '{} -- new Object() - Native object through instantiation'); 
assert(isNative(new Function('alert(1)')), '{} -- Native function through instantiation'); 

// USER OBJECT INSTANTIATION AND INHERITANCE 

var Animal = function() {}; 
var animal = new Animal(); 

var Dog = function() {}; 
Dog.prototype = animal; 
var dog = new Dog(); 

assert(isNative(Animal), 'Animal -- User defined type'); 
assert(isNative(animal), 'animal -- Instance of User defined type'); 

assert(isNative(Dog), 'Dog -- User defined inherited type'); 
assert(isNative(dog), 'dog -- Instance of User defined inherited type'); 

// BUILT IN OBJECTS 

assert(isNative(Object), 'Object -- Built in'); 
assert(isNative(Array), 'Array -- Built in'); 
assert(isNative(Date), 'Date -- Built in'); 
assert(isNative(Boolean), 'Boolean -- Built in'); 
assert(isNative(String), 'String -- Built in'); 
assert(isNative(Function), 'Function -- Built in'); 

// PRIMITIVE TYPES 

assert(!isNative('string'), '"string" - Primitive string'); 
assert(!isNative(1), '1 - Primitive number'); 
assert(!isNative(true), 'true - Primitive boolean'); 
assert(!isNative(null), 'null - Primitive null'); 
assert(!isNative(NaN), 'NaN - Primitive number NotANumber'); 
assert(!isNative(Infinity), 'Infinity - Primitive number Infinity'); 
assert(!isNative(undefined), 'undefined - Primitive value undefined'); 

// HOST OBJECTS 

assert(!isNative(window), 'window -- Host object'); 
assert(!isNative(alert), 'alert -- Host function'); // fails on chrome 
assert(!isNative(document), 'document -- Host object'); 
assert(!isNative(location), 'location -- Host object'); 
assert(!isNative(navigator), 'navigator -- Host object'); 
assert(!isNative(parent), 'parent -- Host object'); 
assert(!isNative(frames), 'frames -- Host object'); 
+0

'process.binding ('evals')। NodeScript.constructor exampleof function === true; 'मुझे पूरा यकीन है कि नोडस्क्रिप्ट को node.js में C++ में परिभाषित किया गया है और तर्कसंगत रूप से" होस्ट ऑब्जेक्ट "के रूप में योग्य होना चाहिए। योरू समाधान गैर ब्राउज़र वातावरण में विस्तार करना मुश्किल है – Raynos

+0

मुझे यकीन नहीं है कि यह सही है या नहीं, लेकिन 'चेतावनी' स्वयं 'मूल' के अनुसार मूल कार्य है। – pimvdb

+0

अच्छी पकड़ @pimvdb, लेकिन केवल क्रोम/वेबकिट पर, मुझे आश्चर्य है क्यों? –

4

यहाँ कि जो स्टैक ट्रेस पुस्तकालय के लिए समस्या का हल है, लेकिन सवाल यहां संतोषजनक ढंग से तैनात उत्तर नहीं मिलता है toString के लिए एक देशी कार्यान्वयन, साथ सभी वस्तुओं को खारिज कर दिया isNative के एक नए संस्करण है। जहां यह दृष्टिकोण उत्तरार्द्ध के लिए विफल रहता है, यह Object, Date, String, Math इत्यादि जैसी सभी अंतर्निहित प्रकार की परिभाषाओं को फ़िल्टर करता है, जो स्वयं होस्ट ऑब्जेक्ट्स नहीं हैं। साथ ही, यह समाधान इस बात पर निर्भर है कि वातावरण देशी/अंतर्निर्मित फ़ंक्शन परिभाषाओं को कैसे आउटपुट करता है (इसमें फ़ंक्शन के लिए "[मूल कोड]" शामिल होना चाहिए)। चूंकि फ़ंक्शन का व्यवहार अलग है, इसलिए इसका नाम बदलकर isUserObject कर दिया गया है।

// USER OBJECT DETECTION 

function isUserObject(obj) { 

    // Should be an instance of an Object 
    if (!(obj instanceof Object)) return false; 

    // Should have a constructor that is an instance of Function 
    if (typeof obj.constructor === 'undefined') return false; 
    if (!(obj.constructor instanceof Function)) return false; 

    // Avoid built-in functions and type definitions 
    if (obj instanceof Function && 
     Function.prototype.toString.call(obj).indexOf('[native code]') > -1) 
      return false; 

    return true; 
} 

// CHECK IF AN OBJECT IS USER-CREATED OR NOT 

if (typeof myObject === 'object' || typeof myObject === 'function') 
    alert(isUserObject(myObject) ? 'User Object' : 'Non-user Object'); 

यहाँ एक list of JsFiddle tests है कि विभिन्न ब्राउज़रों में यह परीक्षण करने के लिए इस्तेमाल किया जा सकता है।

// ASSERT HELPER FUNCTION 

var n = 0; 
function assert(condition, message) { 
    n++; 
    if (condition !== true) { 
     document.write(n + '. FAILS: ' + (message || '(no message)') + '<br/>'); 
    } else { 
     document.write(n + '. PASS: ' + (message || '(no message)') + '<br/>'); 
    } 
} 

// USER CREATED OBJECTS 

assert(isUserObject({}), '{} -- Plain object'); 
assert(isUserObject(function() {}), 'function() {} -- Plain function'); 
assert(isUserObject([]), '[] -- Plain array'); 

assert(isUserObject(/regex/), '/regex/ - Native regex'); 
assert(isUserObject(new Date()), 'new Date() - Native date object through instantiation'); 

assert(isUserObject(new String('string')), 'new String("string") - Native string object through instantiation'); 
assert(isUserObject(new Number(1)), 'new Number(1) - Native number object through instantiation'); 
assert(isUserObject(new Boolean(true)), 'new Boolean(true) - Native boolean object through instantiation'); 
assert(isUserObject(new Array()), 'new Array() - Native array object through instantiation'); 
assert(isUserObject(new Object()), '{} -- new Object() - Native object through instantiation'); 
assert(isUserObject(new Function('alert(1)')), '{} -- Native function through instantiation'); 

// USER OBJECT INSTANTIATION AND INHERITANCE 

var Animal = function() {}; 
var animal = new Animal(); 

var Dog = function() {}; 
Dog.prototype = animal; 
var dog = new Dog(); 

assert(isUserObject(Animal), 'Animal -- User defined type'); 
assert(isUserObject(animal), 'animal -- Instance of User defined type'); 

assert(isUserObject(Dog), 'Dog -- User defined inherited type'); 
assert(isUserObject(dog), 'dog -- Instance of User defined inherited type'); 

// BUILT IN OBJECTS 

assert(!isUserObject(Object), 'Object -- Built in'); 
assert(!isUserObject(Array), 'Array -- Built in'); 
assert(!isUserObject(Date), 'Date -- Built in'); 
assert(!isUserObject(Boolean), 'Boolean -- Built in'); 
assert(!isUserObject(String), 'String -- Built in'); 
assert(!isUserObject(Function), 'Function -- Built in'); 

// PRIMITIVE TYPES 

assert(!isUserObject('string'), '"string" - Primitive string'); 
assert(!isUserObject(1), '1 - Primitive number'); 
assert(!isUserObject(true), 'true - Primitive boolean'); 
assert(!isUserObject(null), 'null - Primitive null'); 
assert(!isUserObject(NaN), 'NaN - Primitive number NotANumber'); 
assert(!isUserObject(Infinity), 'Infinity - Primitive number Infinity'); 
assert(!isUserObject(undefined), 'undefined - Primitive value undefined'); 

// HOST OBJECTS 

assert(!isUserObject(window), 'window -- Host object'); 
assert(!isUserObject(alert), 'alert -- Host function'); 
assert(!isUserObject(document), 'document -- Host object'); 
assert(!isUserObject(location), 'location -- Host object'); 
assert(!isUserObject(navigator), 'navigator -- Host object'); 
assert(!isUserObject(parent), 'parent -- Host object'); 
assert(!isUserObject(frames), 'frames -- Host object');​ 
संबंधित मुद्दे

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