किसी वस्तु के सभी तरीकों को कैसे प्रदर्शित किया जाए?


249

मैं उदाहरण के लिए किसी वस्तु के लिए उपलब्ध सभी तरीकों को सूचीबद्ध करना चाहता हूं:

 alert(show_all_methods(Math));

यह प्रिंट होना चाहिए:

abs, acos, asin, atan, atan2, ceil, cos, exp, floor, log, max, min, pow, random,round, sin, sqrt, tan, 

जवाबों:


298

आप उन Object.getOwnPropertyNames()सभी गुणों को प्राप्त करने के लिए उपयोग कर सकते हैं जो किसी वस्तु से संबंधित हैं, चाहे वह संभव हो या न हो। उदाहरण के लिए:

console.log(Object.getOwnPropertyNames(Math));
//-> ["E", "LN10", "LN2", "LOG2E", "LOG10E", "PI", ...etc ]

तब आप filter()केवल विधियों को प्राप्त करने के लिए उपयोग कर सकते हैं :

console.log(Object.getOwnPropertyNames(Math).filter(function (p) {
    return typeof Math[p] === 'function';
}));
//-> ["random", "abs", "acos", "asin", "atan", "ceil", "cos", "exp", ...etc ]

ES3 ब्राउज़रों (IE 8 और निम्न) में, अंतर्निहित वस्तुओं के गुण असंख्य नहीं हैं। जैसे वस्तुओं windowऔर documentनिर्मित, वे ब्राउज़र और डिजाइन द्वारा सबसे अधिक संभावना गणनीय द्वारा परिभाषित कर रहे हैं नहीं कर रहे हैं।

से ECMA-262 संस्करण 3 :

ग्लोबल ऑब्जेक्ट
एक अद्वितीय वैश्विक ऑब्जेक्ट (15.1) है, जो नियंत्रण से पहले किसी भी निष्पादन संदर्भ में प्रवेश करने पर बनाया जाता है। प्रारंभ में वैश्विक वस्तु में निम्नलिखित गुण होते हैं:

• अंतर्निहित वस्तुएं जैसे कि गणित, स्ट्रिंग, तिथि, पार्सइंट, इत्यादि। इनमें विशेषताएँ {DontEnum} हैं
• अतिरिक्त होस्ट परिभाषित गुण। इसमें ऐसी संपत्ति शामिल हो सकती है जिसका मूल्य वैश्विक वस्तु है; उदाहरण के लिए, HTML डॉक्यूमेंट ऑब्जेक्ट मॉडल में वैश्विक ऑब्जेक्ट की विंडो प्रॉपर्टी ग्लोबल ऑब्जेक्ट ही होती है।

चूंकि नियंत्रण निष्पादन संदर्भों में प्रवेश करता है, और जैसा कि ECMAScript कोड निष्पादित होता है, अतिरिक्त गुणों को वैश्विक ऑब्जेक्ट में जोड़ा जा सकता है और प्रारंभिक गुणों को बदला जा सकता है।

मुझे यह इंगित करना चाहिए कि इसका मतलब यह है कि वे ऑब्जेक्ट ग्लोबल ऑब्जेक्ट के असंख्य गुण नहीं हैं। यदि आप बाकी विनिर्देशन दस्तावेज़ के माध्यम से देखते हैं, तो आप देखेंगे कि इन वस्तुओं के अधिकांश अंतर्निहित गुणों और विधियों में { DontEnum }विशेषता है।


अद्यतन: एक साथी एसओ उपयोगकर्ता, सीएमएस, मेरे ध्यान से संबंधित{ DontEnum } एक आईई बग लाया ।

DontEnum विशेषता की जाँच करने के बजाय, [Microsoft] JScript किसी भी ऑब्जेक्ट में किसी भी संपत्ति पर छोड़ देगा जहाँ ऑब्जेक्ट के प्रोटोटाइप श्रृंखला में समान नाम वाली संपत्ति होती है, जिसमें DontEnum विशेषता होती है।

संक्षेप में, अपने ऑब्जेक्ट गुणों का नामकरण करते समय सावधान रहें। यदि एक ही नाम के साथ एक अंतर्निहित प्रोटोटाइप संपत्ति या विधि है, तो IE for...inलूप का उपयोग करते समय इसे छोड़ देगा ।


एंडी ई, यह इंगित करने के लिए धन्यवाद। स्पष्ट रूप से मुझे इसकी जानकारी नहीं थी और मैं इसे खोदने और यहां उल्लेख करने के आपके प्रयास की सराहना करता हूं। धन्यवाद फिर से :)
रोलैंड बोमन

@ रोलैंड: कोई चिंता नहीं। शायद यह थोड़ा दुखद है, लेकिन मेरे पास मेरे दस्तावेज़ फ़ोल्डर में विनिर्देशन संग्रहीत है, इसलिए वास्तव में बहुत खुदाई की आवश्यकता नहीं है!
एंडी ई

क्या नए जेएस कार्यान्वयन में सभी तरीकों की सूची प्राप्त करने का कोई तरीका नहीं है, फिर? Node.js और V8 की तरह? हम प्रतिबिंब और आत्मनिरीक्षण वस्तुओं को कैसे करते हैं जैसे हम करते थे, जैसे कि मॉक ऑब्जेक्ट फ्रेमवर्क आदि के लिए? मुझे लगा कि मैं सिर्फ JS को भूल गया हूँ, लेकिन मुझे लगता है कि चीजें पिछले कुछ वर्षों में बदल गई हैं :)
d11wtq

2
@ d11wtq, ES5 कार्यान्वयन के साथ, आप आह्वान कर सकते हैं Object.getOwnPropertyNames(), जो कि गैर-विलुप्त होने वाले गुणों और विधियों को भी लौटाएगा।
एंडी ई

चूंकि सभी वस्तुएं अपने प्रोटोटाइप से विरासत में मिली हैं, क्या ऐसा कुछ करना बेहतर नहीं होगा Object.getOwnPropertyNames(Array.prototype) ?
lfender6445

71

यह ES3 के साथ संभव नहीं है क्योंकि गुणों में एक आंतरिक DontEnumगुण होता है जो हमें इन गुणों की गणना करने से रोकता है। दूसरी ओर, ES5, संपत्तियों की गणना क्षमताओं को नियंत्रित करने के लिए संपत्ति विवरणक प्रदान करता है ताकि उपयोगकर्ता-परिभाषित और देशी गुण समान इंटरफ़ेस का उपयोग कर सकें और समान क्षमताओं का आनंद ले सकें, जिसमें गैर-गणना करने योग्य गुणों को प्रोग्रामेटिक रूप से देखने में सक्षम होना शामिल है।

getOwnPropertyNamesसमारोह वस्तु में पारित कर दिया, उन है कि गैर गणनीय हैं सहित के सभी गुण से अधिक की गणना करने में इस्तेमाल किया जा सकता। तब typeofगैर-फ़ंक्शन को फ़िल्टर करने के लिए एक साधारण चेक को नियोजित किया जा सकता है। दुर्भाग्य से, Chrome एकमात्र ऐसा ब्राउज़र है जो वर्तमान में काम करता है।

function getAllMethods(object) {
    return Object.getOwnPropertyNames(object).filter(function(property) {
        return typeof object[property] == 'function';
    });
}

console.log(getAllMethods(Math));

["cos", "pow", "log", "tan", "sqrt", "ceil", "asin", "abs", "max", "exp", "atan2", "random", "round", "floor", "acos", "atan", "min", "sin"]कोई विशेष क्रम में लॉग ।


ES5 सामान के लिए +1। IE9 माना जाता है कि यह सामान अच्छा है इसलिए ES9 पूरी तरह से ES5 का समर्थन करेगा।
एंडी ई

1
@Andy - Microsoft IE9 को बहुत गंभीरता से ले रहा है जो मुझे खुश करता है :)
अनुराग

कंसोल.लॉग (फ़ंक्शन (ए) {return Object.getOwnPropertyNames (a) .filter (फ़ंक्शन (बी) {रिटर्न "फ़ंक्शन" == टाइप ए [बी]}) (गणित)); धन्यवाद!
19h

1
getOwnPropertyNames टिकट है। यह नैशॉर्न में भी काम करता है। उन्होंने सिर्फ जावा ऑब्जेक्ट के तरीकों के नाम बदल दिए, और मैं Object.getOwnPropertyNames (Java) चलाकर नए नामों का पता लगाने में सक्षम था
cayhorstmann

60
var methods = [];
for (var m in obj) {
    if (typeof obj[m] == "function") {
        methods.push(m);
    }
}
alert(methods.join(","));

इस तरह, आपको सभी तरीके मिलेंगे जिन्हें आप कॉल कर सकते हैं obj। इसमें वे विधियाँ शामिल हैं जो इसके प्रोटोटाइप से "विरासत में मिली" (जैसे getMethods()जावा में)। यदि आप केवल उन तरीकों को देखना चाहते हैं जिन्हें objआप सीधे परिभाषित कर सकते हैं hasOwnProperty:

var methods = [];
for (var m in obj) {        
    if (typeof obj[m] == "function" && obj.hasOwnProperty(m)) {
        methods.push(m);
    }
}
alert(methods.join(","));

हाँ, मैं यह भी देख रहा हूँ। जब मैं जैसे documentकिसी चीज़ का उपयोग करता हूं या windowमुझे अधिक भाग्य मिलता है। स्पष्ट रूप से यह थोड़ा अप्रत्याशित है, मुझे नहीं पता कि यह गणित आदि के लिए क्यों काम नहीं करता है
रोलाण्ड बोमन

4
@Roland: यह कारण है documentऔर windowब्राउज़र द्वारा प्रदान की गणनीय गुणों के साथ वस्तुओं रहे हैं, वे पटकथा क्रम का हिस्सा नहीं रहे हैं। मूल वस्तुएं हैं और जाहिर है कि वे गुण नहीं हैं।
एंडी ई

1
किसी भी ई, मैं सहमत नहीं हूँ यह स्पष्ट है। मेरा मतलब है, यह स्पष्ट है क्योंकि हम उन्हें प्रगट नहीं कर सकते। लेकिन मुझे यह तर्क नजर नहीं आता है कि क्यों उन बिल्ट-इन को अपनी संपत्तियों की गणना से बचना चाहिए। बस जिज्ञासु, क्या मानक का कोई हिस्सा है जो कहता है कि इन बिल्ट-इन में अनगिनत गुण नहीं होने चाहिए?
रोलैंड बुमैन

@ रोलैंड: क्षमा करें, मेरा मतलब था कि यह स्पष्ट है कि वे असंख्य नहीं हैं क्योंकि वे फॉर-इन के साथ दिखाई नहीं देते हैं। युक्ति से उद्धरण के लिए मेरा उत्तर नीचे देखें।
एंडी ई

@ मायिक: मैथ एक बिल्ट-इन ऑब्जेक्ट है, जिसके गुण उल्लेखनीय नहीं हैं।
एंडी ई

31

अधिकांश आधुनिक ब्राउज़र समर्थन console.dir(obj), जो किसी वस्तु के सभी गुणों को वापस कर देगा जो उसे अपने निर्माता के माध्यम से विरासत में मिला है। अधिक जानकारी और वर्तमान ब्राउज़र समर्थन के लिए मोज़िला के दस्तावेज़ देखें ।

console.dir(Math)
=> MathConstructor
E: 2.718281828459045
LN2: 0.6931471805599453
...
tan: function tan() { [native code] }
__proto__: Object

4

यहाँ अन्य उत्तर कुछ इस तरह से काम करते हैं जैसे कि गणित, जो एक स्थिर वस्तु है। लेकिन वे किसी वस्तु के उदाहरण के लिए काम नहीं करते हैं , जैसे कि एक तारीख। मुझे काम करने के लिए निम्नलिखित मिला:

function getMethods(o) {
  return Object.getOwnPropertyNames(Object.getPrototypeOf(o))
    .filter(m => 'function' === typeof o[m])
}
//example: getMethods(new Date()):  [ 'getFullYear', 'setMonth', ... ]

https://jsfiddle.net/3xrsead0/

यह मूल प्रश्न (गणित) जैसी किसी चीज़ के लिए काम नहीं करेगा , इसलिए अपनी आवश्यकताओं के आधार पर अपना समाधान चुनें। मैं इसे यहां पोस्ट कर रहा हूं क्योंकि Google ने मुझे इस प्रश्न पर भेजा था लेकिन मैं जानना चाहता था कि वस्तुओं के उदाहरणों के लिए यह कैसे करना है।


3

संक्षिप्त उत्तर यह है कि आप ऐसा नहीं कर सकते हैं Mathऔर Date(मेरे सिर के ऊपर से, मुझे यकीन है कि अन्य हैं) सामान्य वस्तुएं नहीं हैं। इसे देखने के लिए, एक साधारण परीक्षण स्क्रिप्ट बनाएं:

<html>
  <body>
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.1/jquery.min.js"></script>
    <script type="text/javascript">
      $(function() {
        alert("Math: " + Math);
        alert("Math: " + Math.sqrt);
        alert("Date: " + Date);
        alert("Array: " + Array);
        alert("jQuery: " + jQuery);
        alert("Document: " + document);
        alert("Document: " + document.ready);
      });
    </script>
  </body>
</html>

आप इसे एक वस्तु के रूप में प्रस्तुत करते हैं, जिस तरह से दस्तावेज़ समग्र रूप से करता है, लेकिन जब आप वास्तव में कोशिश करते हैं और उस वस्तु को देखते हैं, तो आप देखते हैं कि यह मूल कोड है और कुछ ने गणना के लिए उसी तरह से उजागर नहीं किया है।


1

Mathस्टैटिक मेथड है, जहाँ आप सीधे कॉल कर सकते हैं, Math.abs()जबकि Dateस्टैटिक मेथड जैसी है Date.now()और इंस्टेंस मेथड भी है जहाँ आपको var time = new Date()कॉल करने के लिए पहले नया इंस्ट्रक्शन बनाने की आवश्यकता है time.getHours()

// The instance method of Date can be found on `Date.prototype` so you can just call:
var keys = Object.getOwnPropertyNames(Date.prototype);

// And for the static method
var keys = Object.getOwnPropertyNames(Date);

// But if the instance already created you need to
// pass its constructor
var time = new Date();
var staticKeys = Object.getOwnPropertyNames(time.constructor);
var instanceKeys = Object.getOwnPropertyNames(time.constructor.prototype);

बेशक आपको वास्तविक विधि के नाम प्राप्त करने के लिए स्थिर विधि के लिए प्राप्त कुंजियों को फ़िल्टर करना होगा , क्योंकि आप यह भी प्राप्त कर सकते हैं length, nameकि सूची में कोई फ़ंक्शन नहीं है।

लेकिन अगर हम कक्षा से सभी उपलब्ध विधि प्राप्त करना चाहते हैं जो किसी अन्य वर्ग का विस्तार करें?
बेशक आपको प्रोटोटाइप की जड़ के माध्यम से स्कैन करना होगा जैसे कि उपयोग करना __proto__। अपना समय बचाने के लिए आप स्टैटिक विधि और डीप मेथड इंस्टेंस प्राप्त करने के लिए नीचे स्क्रिप्ट का उपयोग कर सकते हैं।

// var keys = new Set();
function getStaticMethods(keys, clas){
    var keys2 = Object.getOwnPropertyNames(clas);

    for(var i = 0; i < keys2.length; i++){
        if(clas[keys2[i]].constructor === Function)
            keys.add(keys2[i]);
    }
}

function getPrototypeMethods(keys, clas){
    if(clas.prototype === void 0)
        return;

    var keys2 = Object.getOwnPropertyNames(clas.prototype);
    for (var i = keys2.length - 1; i >= 0; i--) {
        if(keys2[i] !== 'constructor')
            keys.add(keys2[i]);
    }

    var deep = Object.getPrototypeOf(clas);
    if(deep.prototype !== void 0)
        getPrototypeMethods(keys, deep);
}

// ====== Usage example ======
// To avoid duplicate on deeper prototype we use `Set`
var keys = new Set();
getStaticMethods(keys, Date);
getPrototypeMethods(keys, Date);

console.log(Array.from(keys));

यदि आप निर्मित आवृत्ति से विधियाँ प्राप्त करना चाहते हैं, तो constructorइसे पास करना न भूलें ।


0

मेरा मानना ​​है कि एक साधारण ऐतिहासिक कारण है कि आप उदाहरण के लिए ऐरे जैसी अंतर्निहित वस्तुओं के तरीकों पर अधिक ध्यान नहीं दे सकते। यहाँ पर क्यों:

विधियाँ प्रोटोटाइप-ऑब्जेक्ट के गुण हैं, Object.prototyp कहते हैं। इसका मतलब है कि सभी ऑब्जेक्ट-इंस्टेंस उन विधियों को इनहेरिट करेंगे। इसलिए आप किसी भी ऑब्जेक्ट पर उन तरीकों का उपयोग कर सकते हैं। उदाहरण के लिए .toString () कहें।

तो यदि विधियां अमूल्य थीं, और मैं {a: 123} के साथ कहना चाहूंगा: "for (in a: 123}) {...}" (क्या होगा)? उस पाश को कितनी बार निष्पादित किया जाएगा?

यह हमारे उदाहरण में एकल कुंजी 'a' के लिए एक बार पुनरावृत्त होगा। लेकिन यह भी हर के लिए एक बार गणनीय Object.prototype की संपत्ति। इसलिए यदि विधियाँ अनुप्राणित होती हैं (डिफ़ॉल्ट रूप से), तो किसी भी वस्तु पर कोई भी लूप उसके सभी विरासत में मिले तरीकों पर लूप होगा।


1
चूंकि प्रायमेटिक्स आमतौर पर एक प्रोटोटाइप से विरासत में मिलते हैं, यह Object.getOwnPropertyNames(Array.prototype)उदाहरण के लिए संभव है
lfender6445

क्या आप का मतलब है तरीके Object.prototype के गुण हैं। ? प्रत्येक संपत्ति Object.prototype के मामले में ऑब्जेक्ट की संपत्ति है
डिबग्मोडे
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.