जावास्क्रिप्ट कार्य में 'a' ['toUpperCase'] () कैसे और क्यों करता है?


209

जावास्क्रिप्ट मुझे आश्चर्यचकित करता है और यह एक और उदाहरण है। मैं अभी कुछ कोड भर आया था जो मुझे पहले समझ में नहीं आया था। इसलिए मैंने इसे डिबग किया और इस खोज में आया:

alert('a'['toUpperCase']());  //alerts 'A'

अब यह स्पष्ट होना चाहिए कि क्या toUpperCase()स्ट्रिंग प्रकार के सदस्य के रूप में परिभाषित किया गया है, लेकिन शुरू में मुझे इससे कोई मतलब नहीं था।

वैसे भी,

  • क्या यह कार्य toUpperCase'a' का सदस्य है? या फिर पर्दे के पीछे कुछ और चल रहा है?
  • कोड मैं पढ़ रहा था एक समारोह के रूप में निम्नानुसार है:

    function callMethod(method) {
        return function (obj) {
            return obj[method](); //**how can I be sure method will always be a member of obj**
        }
    }
    
    var caps2 = map(['a', 'b', 'c'], callMethod('toUpperCase')); // ['A','B','C'] 
    // ignoring details of map() function which essentially calls methods on every 
    // element of the array and forms another array of result and returns it
    

    यह किसी भी वस्तु पर किसी भी तरीके को कॉल करने के लिए थोड़े सामान्य कार्य है । लेकिन इसका मतलब यह है कि निर्दिष्ट विधि पहले से ही निर्दिष्ट वस्तु का एक अंतर्निहित सदस्य होगी?

मुझे यकीन है कि मैं जावास्क्रिप्ट कार्यों की बुनियादी अवधारणा की कुछ गंभीर समझ को याद कर रहा हूं। कृपया इसे समझने में मेरी मदद करें।


24
किसी ऑब्जेक्ट के गुणों तक पहुँचने के दो तरीके हैं: डॉट नोटेशन और ब्रैकेट नोटेशन। थोड़ा संबंधित: stackoverflow.com/a/11922384/218196 । आप कोष्ठक संकेतन के बारे में पहले से ही जानते हैं क्योंकि सरणी तत्वों तक पहुँचने पर आप हमेशा इसका उपयोग करते हैं arr[5]:। यदि संख्या जहाँ मान्य पहचानकर्ता नाम आप डॉट नोटेशन का उपयोग कर सकते हैं arr.5:।
फेलिक्स क्लिंग

2
यह वैसा ही है 5['toString']()
0x499602D2

1
भी संबंधित हैं: stackoverflow.com/q/4968406/218196
फेलिक्स क्लिंग

संबंधित पढ़ना: 1) वंशानुक्रम और प्रोटोटाइप श्रृंखला: developer.mozilla.org/en-US/docs/JavaScript/Guide/… 2) जावास्क्रिप्ट आदिम का गुप्त जीवन: javascriptweblog.word.com.com/2010/09/27/…
थरोट

21
पहली बार में मैंने सोचा था कि शीर्षक "जावास्क्रिप्ट कैसे और क्यों काम करता है?" ठीक है।
समस्याग्रस्त

जवाबों:


293

इसे तोड़ने के लिए।

  • .toUpperCase() की एक विधि है String.prototype
  • 'a'एक आदिम मूल्य है, लेकिन अपने ऑब्जेक्ट प्रतिनिधित्व में परिवर्तित हो जाता है
  • ऑब्जेक्ट गुण / विधियों, डॉट और ब्रैकेट नोटेशन तक पहुंचने के लिए हमारे पास दो संभावित नोटेशन हैं

इसलिए

'a'['toUpperCase'];

संपत्ति पर ब्रैकेट नोटेशन के माध्यम से पहुंच toUpperCaseहै String.prototype। चूंकि यह संपत्ति एक विधि का संदर्भ देती है , इसलिए हम इसे संलग्न करके लागू कर सकते हैं()

'a'['toUpperCase']();

यह एक प्रफुल्लित करने वाला साक्षात्कार प्रश्न होगा
FluffyBeing

78

foo.barऔर foo['bar']समान हैं, इसलिए आपके द्वारा पोस्ट किया गया कोड समान है

alert('a'.toUpperCase())

उपयोग करते समय foo[bar](उद्धरणों की कमी पर ध्यान दें) आप शाब्दिक नाम का उपयोग नहीं करते हैं, barलेकिन चर का जो भी मूल्य है bar। इसलिए आप एक गतिशील संपत्ति के नाम का उपयोग करने foo[]की foo.अनुमति देने के बजाय अंकन का उपयोग कर रहे हैं।


आइए नजर डालते हैं callMethod:

सबसे पहले, यह एक फ़ंक्शन देता है जो objइसके तर्क के रूप में लेता है। जब वह फ़ंक्शन निष्पादित होता है, तो वह methodउस ऑब्जेक्ट पर कॉल करेगा । इसलिए दी गई विधि को या तो objस्वयं या कहीं और अपनी प्रोटोटाइप श्रृंखला पर मौजूद होना चाहिए ।

toUpperCaseउस विधि के मामले में से आता है String.prototype.toUpperCase- यह हर एक स्ट्रिंग के लिए विधि की एक अलग प्रतिलिपि है कि मौजूद है बेवकूफ होगा।


25

आप या तो किसी भी ऑब्जेक्ट के सदस्यों को .propertyNameनोटेशन या ["propertyName"]नोटेशन से एक्सेस कर सकते हैं । यह जावास्क्रिप्ट भाषा की विशेषता है। यह सुनिश्चित करने के लिए कि सदस्य वस्तु में है, बस जाँच करें, यदि यह परिभाषित है:

function callMethod(method) {
    return function (obj) {
        if (typeof(obj[method]) == 'function') //in that case, check if it is a function
           return obj[method](); //and then invoke it
    }
}

17

मूल रूप से जावास्क्रिप्ट सब कुछ एक वस्तु के रूप में व्यवहार करता है, या बल्कि प्रत्येक वस्तु को एक शब्दकोश / साहचर्य-सरणी के रूप में देखा जा सकता है। और फ़ंक्शन / विधियों को ऑब्जेक्ट के लिए सटीक उसी तरीके से परिभाषित किया जाता है - इस साहचर्य सरणी में एक प्रविष्टि के रूप में।

इसलिए अनिवार्य रूप से, आप 'ए' ऑब्जेक्ट (जो कि एक स्ट्रिंग प्रकार है, इस मामले में) की 'कॉलिंग (' 'नोटिस करें' () '' टॉपर कैस ') को देखें।

यहाँ मेरे सिर के शीर्ष का कुछ कोड है:

function myObject(){
    this.msg = "hey there! ;-)";
    this.woop = function(){
        alert(this.msg); //do whatever with member data
    }
}

var obj = new myObject();
alert( obj.msg );
alert( obj['msg'] );
obj['woop']();

10

anyObject['anyPropertyName']समस्याग्रस्त वर्णों के न anyObject.anyPropertyNameहोने के समान ही है anyPropertyName

MDN से ऑब्जेक्ट्स के साथ कार्य करना देखें ।

toUpperCaseविधि प्रकार स्ट्रिंग से जुड़ा हुआ है। जब आप किसी कार्य को एक आदिम मूल्य पर कहते हैं 'a', तो, यह स्वचालित रूप से एक वस्तु को बढ़ावा देता है, यहां एक स्ट्रिंग :

संदर्भों में जहां एक विधि को एक आदिम स्ट्रिंग पर या किसी संपत्ति की खोज के लिए आमंत्रित किया जाता है, जावास्क्रिप्ट स्वचालित रूप से स्ट्रिंग आदिम लपेटेगा और विधि को कॉल करेगा या संपत्ति की खोज करेगा।

आप देख सकते हैं कि कार्य लॉगिंग से मौजूद है String.prototype.toUpperCase


9

तो जावास्क्रिप्ट में, objectsहैं objects। वे इस प्रकृति के हैं {}। ऑब्जेक्ट गुण इनमें से किसी एक का उपयोग करके सेट किया जा सकता है: a.greeting = 'hello';या a['greeting'] = 'hello';। दोनों तरीके काम करते हैं।

पुनर्प्राप्ति समान कार्य करती है। a.greeting(बिना उद्धरण के) है 'hello', a['greeting']है 'hello'। अपवाद: यदि संपत्ति एक संख्या है, तो केवल ब्रैकेट विधि काम करती है। डॉट विधि नहीं है।

तो संपत्ति के 'a'साथ एक वस्तु 'toUpperCase'है जो वास्तव में एक फ़ंक्शन है। आप फ़ंक्शन को पुनः प्राप्त कर सकते हैं और इसे बाद में किसी भी तरह से कॉल कर सकते हैं: 'a'.toUpperCase()या 'a'['toUpperCase']()

लेकिन नक़्शे के फंक्शन को लिखने का बेहतर तरीका यह है कि फ़िर

var caps = ['a','b','c'].map( function(char) { return char.toUpperCase(); } )

किसको callMethodफंक्शन की ज़रूरत है ?


खूबसूरती से समझाया :-)
एलिशा सेनू

6

हर जावास्क्रिप्ट ऑब्जेक्ट एक हैश तालिका है इस प्रकार आप एक कुंजी निर्दिष्ट करके अपने सदस्यों तक पहुँच सकते हैं। उदाहरण के लिए, यदि एक चर एक स्ट्रिंग है, तो इसमें टॉपर कैस फ़ंक्शन होना चाहिए। इसलिए, आप इसे लागू कर सकते हैं

var str = "a"
str['toUpperCase'](). // you get the method by its name as a key and invoke it.

इसलिए, इनलाइन स्ट्रॉग द्वारा, आप नीचे कर सकते हैं

"a"["toUpperCase"]()

6

toUpperCase एक मानक जावास्क्रिप्ट विधि है: https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/String/toUpperCase

इस तरह 'a'['toUpperCase']()से काम करने का कारण यह है कि टॉपरकेस फ़ंक्शन स्ट्रिंग ऑब्जेक्ट की एक संपत्ति है 'a'। आप का उपयोग कर object[property]या एक वस्तु पर गुणों का संदर्भ कर सकते हैं object.property। वाक्य-विन्यास 'a''toUpperCase' इंगित करता है कि आप 'a' स्ट्रिंग ऑब्जेक्ट की 'toUppercase' को संदर्भित कर रहे हैं, और फिर इसे कॉल कर रहे हैं ()।


4

लेकिन इसका मतलब यह है कि निर्दिष्ट विधि पहले से ही निर्दिष्ट वस्तु का एक अंतर्निहित सदस्य होगी?

नहीं। कोई व्यक्ति किसी वस्तु में गुजर सकता है

  1. नाम की कोई संपत्ति नहीं है toUpperCase; या
  2. एक संपत्ति है जिसका नाम toUpperCaseएक फ़ंक्शन नहीं है

पहले मामले में, एक त्रुटि को फेंक दिया जाएगा क्योंकि एक संपत्ति तक पहुंचना जो रिटर्न मौजूद नहीं है undefined, और हम undefinedएक फ़ंक्शन के रूप में आह्वान नहीं कर सकते ।

दूसरे मामले में, एक त्रुटि होगी क्योंकि फिर से, हम एक फ़ंक्शन के रूप में एक गैर-फ़ंक्शन को आमंत्रित नहीं कर सकते।

याद रखें कि जावास्क्रिप्ट बहुत शिथिल टाइप की भाषा है। कम या कोई प्रकार की जाँच तब तक नहीं होती है जब तक कि उसे करना न पड़े। आपके द्वारा दिखाए गए कोड कुछ मामलों में काम करते हैं क्योंकि, उन मामलों में, पास की गई वस्तु में एक संपत्ति होती है जिसका नाम toUpperCaseएक फ़ंक्शन होता है।

यह तथ्य कि objतर्क सही गुणों की गारंटी नहीं है, जावास्क्रिप्ट को बिल्कुल भी परेशान नहीं करता है, इसलिए बोलने के लिए। यह एक "प्रतीक्षा करें और देखें" रवैया अपनाता है, और एक त्रुटि तब तक नहीं फेंकता जब तक कि वास्तविक समस्या रन टाइम पर न हो।


4

जावास्क्रिप्ट में लगभग सब कुछ एक वस्तु के रूप में माना जा सकता है। आपके मामले में वर्णमाला स्वयं एक स्ट्रिंग ऑब्जेक्ट के रूप में कार्य करती है और toUpperCaseइसे इसकी विधि के रूप में लागू किया जा सकता है। वर्ग कोष्ठक वस्तु गुणों तक पहुँचने का सिर्फ एक वैकल्पिक तरीका है और चूंकि toUpperCaseएक विधि है इसलिए बनाने के ()बगल में सरल ब्रैकेट की आवश्यकता होती है ।['toUpperCase']['toUpperCase']()

'a'['toUpperCase']() के बराबर है 'a'.toUpperCase()

'a'['toUpperCase']() // returns A
'a'.toUpperCase() // returns A

3

यहां ध्यान देने योग्य बात यह है कि, चूंकि जावास्क्रिप्ट एक गतिशील भाषा है, प्रत्येक वस्तु, अनिवार्य रूप से, बस एक गौरवशाली हैश-मैप ( कुछ अपवादों के साथ ) है। और जावास्क्रिप्ट ऑब्जेक्ट में सब कुछ दो तरीकों से एक्सेस किया जा सकता है - ब्रैकेट नोटेशन और डॉट नोटेशन।

मैं जल्दी से आपके प्रश्न के पहले भाग का उत्तर देने वाली दो सूचनाओं पर जाऊंगा, और फिर मैं दूसरे भाग में पहुँचूँगा।

ब्रैकेट संकेतन

यह मोड अन्य प्रोग्रामिंग भाषाओं में हैशमैप और सरणियों तक पहुंचने के समान है। आप इस सिंटैक्स का उपयोग करके किसी भी घटक (डेटा (अन्य ऑब्जेक्ट्स सहित) या फ़ंक्शन) तक पहुंच सकते हैं ।

यह वही है जो आपके उदाहरण में आप कर रहे हैं। आपके पास 'a', जो एक स्ट्रिंग है (और वर्ण शाब्दिक नहीं है, जैसे कि यह C ++ जैसी भाषा में होगा)।

ब्रैकेट नोटेशन का उपयोग करते हुए, आप इसकी toUpperCaseविधि का उपयोग करते हैं। लेकिन इसे एक्सेस करना अभी भी पर्याप्त नहीं है; alertउदाहरण के लिए, जावास्क्रिप्ट में टाइप करना , विधि को नहीं कहता है। यह सिर्फ एक साधारण बयान है। फ़ंक्शन को कॉल करने के लिए, आपको कोष्ठक जोड़ने की आवश्यकता है: alert()एक साधारण डायलॉग बॉक्स युक्त दिखाता है undefined, क्योंकि इसमें कोई पैरामीटर नहीं मिला है। अब हम आपके कोड को समझने के लिए इस ज्ञान का उपयोग कर सकते हैं, जो बन जाता है:

alert('a'.toUpperCase());

जो बहुत अधिक पठनीय है।

वास्तव में, इसे थोड़ा बेहतर समझने का एक अच्छा तरीका निम्नलिखित जावास्क्रिप्ट को निष्पादित करना है:

alert(alert)

यह alertएक फ़ंक्शन ऑब्जेक्ट को पास करके कॉल करता है, साथ ही alert, दूसरे अलर्ट को निष्पादित किए बिना भी। क्या दिखाया गया है (Chrome 26 में, कम से कम) निम्नलिखित है:

function alert() { [native code] } 

कॉलिंग:

alert(alert())

लगातार दो संदेश बॉक्स दिखाता है undefined। यह समझाना आसान है: आंतरिक alert()पहले निष्पादित हो जाता है, दिखाता है undefined(क्योंकि इसमें कोई पैरामीटर नहीं था) और कुछ भी नहीं देता है। बाहरी चेतावनी को आंतरिक चेतावनी का रिटर्न मान प्राप्त होता है - जो कुछ भी नहीं है, और undefinedसंदेश बॉक्स में भी दिखाता है।

JsFiddle पर सभी मामलों की कोशिश करो!

डॉट नोटेशन

यह अधिक मानक दृष्टिकोण है, जो किसी ऑब्जेक्ट के सदस्यों को डॉट ( .) ऑपरेटर का उपयोग करके एक्सेस करने की अनुमति देता है । यह वही है जो आपका कोड डॉट नोटेशन में दिखाई देगा:

alert('a'.toUpperCase())

बहुत अधिक पठनीय। तो हमें डॉट नोटेशन का उपयोग कब करना चाहिए, और हमें ब्रैकेट नोटेशन का उपयोग कब करना चाहिए?

तुलना

दो तरीकों के बीच मुख्य अंतर शब्दार्थ है। कुछ अन्य विवरण भी हैं, लेकिन मैं एक सेकंड में उन तक पहुँचूँगा। सबसे महत्वपूर्ण यह है कि आप वास्तव में क्या करना चाहते हैं - अंगूठे का एक नियम यह है कि आप अच्छी तरह से स्थापित फ़ील्ड और किसी ऑब्जेक्ट के तरीकों के लिए डॉट नोटेशन का उपयोग करते हैं , और जब आप वास्तव में एक हैश मैप के रूप में अपनी वस्तु का उपयोग कर रहे हैं, तो उसके लिए ब्रैकेट-नोटेशन।

यह नियम इतना महत्वपूर्ण क्यों है, इसका एक बड़ा उदाहरण आपके उदाहरण में दिखाया जा सकता है - चूँकि कोड कोष्ठक संकेतन का उपयोग उस स्थान पर किया जाता है जहाँ डॉट संकेतन बहुत अधिक समझदार होता, यह कोड को पढ़ने में कठिन बनाता है। और यह एक बुरी बात है, क्योंकि कोड को लिखे जाने की तुलना में कई गुना अधिक पढ़ा जाता है

कुछ मामलों में, आपको ब्रैकेट नोटेशन का उपयोग करना होगा, भले ही डॉट नोटेशन का उपयोग करना अधिक समझदार हो:

  • यदि किसी वस्तु के सदस्य के नाम में एक या अधिक रिक्त स्थान या कोई अन्य विशेष वर्ण हैं, तो आप डॉट नोटेशन का उपयोग नहीं कर सकते हैं: foo.some method()यह काम नहीं करता है, लेकिन foo["some method"]()करता है;

  • यदि आपको किसी ऑब्जेक्ट के सदस्यों को गतिशील रूप से एक्सेस करने की आवश्यकता है, तो आप ब्रैकेट नोटेशन का उपयोग करके भी अटक जाते हैं;

उदाहरण:

for(var i = 0; i < 10; ++i) {
   foo["method" + i](); 
 }

लब्बोलुआब यह है कि आपको ऑब्जेक्ट को हैश मैप ( foods["burger"].eat()) और डॉट सिंटैक्स के रूप में "वास्तविक" फ़ील्ड और विधियों ( enemy.kill()) के साथ काम करते समय ब्रैकेट सिंटैक्स का उपयोग करना चाहिए । जावास्क्रिप्ट को एक गतिशील भाषा होने के साथ, "वास्तविक" फ़ील्ड्स और किसी ऑब्जेक्ट के तरीकों और "अन्य" डेटा के भीतर संग्रहीत लाइन के बीच की रेखा खाली हो सकती है। लेकिन जब तक आप उन्हें भ्रमित करने के तरीकों में मिश्रण नहीं करते हैं, तब तक आपको ठीक होना चाहिए।


अब, आपके शेष प्रश्न पर (अंत में !: P)।

मैं कैसे सुनिश्चित कर सकता हूं कि विधि हमेशा ओब्ज का सदस्य होगी

आप नहीं कर सकते। कोशिश करो। derpएक स्ट्रिंग पर कॉल करने का प्रयास करें । आपको इसकी पंक्तियों में एक त्रुटि मिलेगी:

Uncaught TypeError: Object a has no method 'derp' 

यह किसी भी वस्तु पर किसी भी तरीके को कॉल करने के लिए थोड़े सामान्य कार्य है। लेकिन इसका मतलब यह है कि निर्दिष्ट विधि पहले से ही निर्दिष्ट वस्तु का एक अंतर्निहित सदस्य होगी?

हां, आपके मामले में यह होना चाहिए। अन्यथा आप ऊपर बताई गई त्रुटि के साथ समाप्त होते हैं। हालाँकि, आपको फ़ंक्शन में उपयोग करने की आवश्यकता नहीं है । आप अपनी स्वयं की कार्यक्षमता जोड़ सकते हैं जो तब मानचित्र फ़ंक्शन द्वारा उपयोग की जाती है। यहाँ एक कठिन-कूट विधि है जो सभी अक्षरों को एक बड़े अक्षर में बदल देती है:return obj[method]();callMethod()

function makeCap()
{
    return function(obj) {
        return obj.toUpperCase();
    }
}

var caps2 = map(['a', 'b', 'c'], makeCap()); // ['A','B','C'] 
console.log(caps2)

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


नोट: यह प्रश्न, स्रोत में कोड द्वारा उपयोग किए गए मानचित्र फ़ंक्शन का कोड है

function map(arr, iterator) {
  var narr = [];
  for (var i = 0; i < arr.length; i++) narr.push(iterator(arr[i], i));
  return narr;
}

2

यदि आपका यह पूछना कि यह वास्तव में कैसे काम करता है जो मैंने इसे कैसे पढ़ा है। ठीक है यह एक सरल गणितीय कार्य है। इसे समझने के लिए आपको अस्की टेबल देखने की जरूरत है। जो प्रत्येक अक्षर को एक संख्यात्मक मान प्रदान करता है। इसे कवर करने के लिए प्रतियोगिता केवल उदाहरण के लिए इतना करने के लिए एक लॉकेट स्टेटमेंट का उपयोग करती है यदि (ChcrValue> 80 && charValue <106) // यह लोअर केस लेटर्स का सेट है तो charValue = charValue - 38; // निचले सेट और ऊपरी सेट के बीच की दूरी

यह इतना आसान है, मैंने वास्तव में सही मूल्यों को देखने की जहमत नहीं उठाई, लेकिन यह मूल रूप से सभी निचले अक्षरों को बड़े पैमाने पर मूल्य में बदल रहा है।


यह प्रश्न कैसे संबंधित है?
क्साडंक

2
@ भाग, उन्होंने पूछा कि कैसे और क्यों 'a'['toUpperCase']()काम करते हैं। लेकिन गलतफहमी समझ में आती है, अगर किसी ने सवाल नहीं पढ़ा।
लार्स

gr8 उत्तर, चूंकि कोई शैली नहीं text-transform: uppercaseजोड़ी गई थी, मैं इस बात के लिए तैयार था कि कैसे जेएस मामले को बदलने में कामयाब रहे, संदेह को दूर किया और एक या दो चीजें सीखीं। बहुत बहुत धन्यवाद।
dkjain
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.