जावास्क्रिप्ट में चर का दायरा क्या है?


2011

जावास्क्रिप्ट में चर का दायरा क्या है? क्या उनके पास एक कार्यक्षेत्र के बाहर समान विरोध है? या इससे भी फर्क पड़ता है? इसके अलावा, यदि विश्व स्तर पर परिभाषित किया गया है, तो चर कहाँ संग्रहीत किए जाते हैं?


4
इस मुद्दे को ध्यान में रखने के लिए यहां एक और अच्छा लिंक है: " जावास्क्रिप्ट दायरे की व्याख्या और बंद "।
पूर्ण-स्टैक सॉफ्टवेयर इंजीनियर

9
यहाँ एक लेख है जो इसे बहुत अच्छी तरह से समझाता है। जावास्क्रिप्ट चर दायरे के बारे में आपको जो कुछ भी जानने की जरूरत है
सौरभ पारख

2
काइल सिम्पसन की पहले से उल्लेखित ई-पुस्तक गितुब पर पढ़ने के लिए उपलब्ध है, और यह आपको बताती है कि आपको जावास्क्रिप्ट स्कोप और क्लोज़र के बारे में जानने की आवश्यकता है। आप इसे यहां पा सकते हैं: github.com/getify/You-Dont-Know-JS/blob/master/… यह "आप जेएस नहीं जानते" पुस्तक श्रृंखला का हिस्सा है , जो हर उस व्यक्ति के लिए बहुत अच्छा है जो जानना चाहते हैं जावास्क्रिप्ट के बारे में अधिक।
3ric82

जवाबों:


2534

TLDR

जावास्क्रिप्ट में शाब्दिक (स्थैतिक भी कहा जाता है) स्कूपिंग और क्लोजर। इसका मतलब है कि आप सोर्स कोड को देखकर किसी पहचानकर्ता का दायरा बता सकते हैं।

चार स्कोप हैं:

  1. ग्लोबल - सब कुछ द्वारा दिखाई
  2. फ़ंक्शन - एक फ़ंक्शन के भीतर दिखाई देता है (और इसके उप-फ़ंक्शन और ब्लॉक)
  3. ब्लॉक - एक ब्लॉक के भीतर दिखाई देता है (और इसके उप-ब्लॉक)
  4. मॉड्यूल - एक मॉड्यूल के भीतर दिखाई दे रहा है

वैश्विक और मॉड्यूल दायरे के विशेष मामलों के बाहर, चर var(फ़ंक्शन स्कोप), let(ब्लॉक स्कोप) और const(ब्लॉक स्कोप) का उपयोग करके घोषित किया जाता है । पहचानकर्ता घोषणा के अधिकांश अन्य रूपों में सख्त मोड में ब्लॉक गुंजाइश है।

अवलोकन

स्कोप कोडबेस का वह क्षेत्र है जिसके ऊपर एक पहचानकर्ता मान्य है।

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

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

ये जुड़े हुए शाब्दिक वातावरण एक गुंजाइश "श्रृंखला" बनाते हैं। आइडेंटिफ़ायर रिज़ॉल्यूशन इस श्रृंखला के साथ मेल खाने वाले आइडेंटिफ़ायर की खोज की प्रक्रिया है।

पहचानकर्ता संकल्प केवल एक दिशा में होता है: बाहर की ओर। इस तरह, बाहरी शाब्दिक वातावरण आंतरिक शाब्दिक वातावरण में "नहीं" देख सकते हैं।

जावास्क्रिप्ट में पहचानकर्ता का दायरा तय करने के तीन महत्वपूर्ण कारक हैं :

  1. कैसे एक पहचानकर्ता घोषित किया गया था
  2. जहां एक पहचानकर्ता घोषित किया गया था
  3. चाहे आप सख्त मोड में हों या गैर-सख्त मोड

कुछ तरीकों की पहचान की जा सकती है:

  1. var, letऔरconst
  2. कार्य मापदंडों
  3. ब्लॉक पैरामीटर पकड़ो
  4. समारोह की घोषणा
  5. नामित कार्य अभिव्यक्तियाँ
  6. वैश्विक वस्तु पर कथित रूप से परिभाषित गुण (यानी varगैर-सख्त मोड में गायब )
  7. import बयान
  8. eval

कुछ स्थानों के पहचानकर्ता घोषित किए जा सकते हैं:

  1. वैश्विक संदर्भ
  2. शरीर की क्रिया
  3. साधारण ब्लॉक
  4. एक नियंत्रण संरचना के शीर्ष (जैसे। लूप, यदि, जबकि आदि)
  5. नियंत्रण संरचना शरीर
  6. मॉड्यूल

घोषणा शैलियाँ

वर

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

चलो और कास्ट

पहचानकर्ताओं ने उपयोग करने की घोषणा की letऔर const ब्लॉक स्कोप है , इसके अलावा जब वे सीधे वैश्विक संदर्भ में घोषित किए जाते हैं, तो उस स्थिति में उनके पास वैश्विक स्कोप होता है।

ध्यान दें: let, constऔर var सभी फहराया जाता है । इसका मतलब यह है कि परिभाषा की उनकी तार्किक स्थिति उनके संलग्न दायरे (ब्लॉक या फ़ंक्शन) में सबसे ऊपर है। हालांकि, चर ने उपयोग की घोषणा की letऔर constतब तक पढ़ा या सौंपा नहीं जा सकता जब तक कि नियंत्रण ने स्रोत कोड में घोषणा के बिंदु को पारित नहीं किया। अंतरिम अवधि को अस्थायी मृत क्षेत्र के रूप में जाना जाता है।

function f() {
    function g() {
        console.log(x)
    }
    let x = 1
    g()
}
f() // 1 because x is hoisted even though declared with `let`!

फ़ंक्शन पैरामीटर नाम

फ़ंक्शन बॉडी में फ़ंक्शन पैरामीटर नाम स्कोप किए जाते हैं। ध्यान दें कि इसमें थोड़ी जटिलता है। पैरामीटर सूची के ऊपर डिफ़ॉल्ट तर्क के रूप में घोषित कार्य , और फ़ंक्शन का निकाय नहीं।

समारोह की घोषणा

फ़ंक्शन घोषणाओं में सख्त मोड में ब्लॉक गुंजाइश है और गैर-सख्त मोड में फ़ंक्शन गुंजाइश है। नोट: गैर-सख्त मोड विभिन्न ब्राउज़रों के quirky ऐतिहासिक कार्यान्वयन के आधार पर आकस्मिक नियमों का एक जटिल समूह है।

नामित कार्य अभिव्यक्तियाँ

नामित फ़ंक्शन अभिव्यक्तियों को स्वयं के लिए स्कोप किया जाता है (उदाहरण के लिए पुनरावृत्ति के उद्देश्य से)।

वैश्विक वस्तु पर स्पष्ट रूप से परिभाषित गुण

गैर-सख्त मोड में, वैश्विक वस्तु पर स्पष्ट रूप से परिभाषित गुण वैश्विक गुंजाइश रखते हैं, क्योंकि वैश्विक ऑब्जेक्ट गुंजाइश श्रृंखला के शीर्ष पर बैठता है। सख्त मोड में इनकी अनुमति नहीं है।

eval

में evalतार, चर घोषित का उपयोग कर varवर्तमान क्षेत्र में रखा जाएगा, या, यदि evalवैश्विक वस्तु पर गुण के रूप में, परोक्ष रूप से प्रयोग किया जाता है।

उदाहरण

निम्नलिखित नाम से एक सन्दर्भ फेंक देगा x, क्योंकि नाम yऔर zफ़ंक्शन का कोई अर्थ नहीं है f

function f() {
    var x = 1
    let y = 1
    const z = 1
}
console.log(typeof x) // undefined (because var has function scope!)
console.log(typeof y) // undefined (because the body of the function is a block)
console.log(typeof z) // undefined (because the body of the function is a block)

निम्नलिखित के लिए एक ReferenceError फेंक देते हैं yऔर zनहीं, बल्कि के लिए xकी वजह से दृश्यता, xब्लॉक से विवश नहीं है। ब्लॉक जो नियंत्रण संरचनाओं के निकायों को परिभाषित करते हैं if, forऔर while, इसी तरह व्यवहार करते हैं।

{
    var x = 1
    let y = 1
    const z = 1
}
console.log(x) // 1
console.log(typeof y) // undefined because `y` has block scope
console.log(typeof z) // undefined because `z` has block scope

निम्नलिखित में, xलूप के बाहर दिखाई देता है क्योंकि varफ़ंक्शन गुंजाइश है:

for(var x = 0; x < 5; ++x) {}
console.log(x) // 5 (note this is outside the loop!)

... इस व्यवहार के कारण आपको varलूप में उपयोग किए जाने वाले घोषित चर पर बंद होने से सावधान रहने की आवश्यकता है । यहां xघोषित चर का केवल एक उदाहरण है, और यह लूप के बाहर तार्किक रूप से बैठता है।

निम्नलिखित प्रिंट 5, पांच बार, और फिर लूप 5के console.logबाहर छठी बार प्रिंट करता है:

for(var x = 0; x < 5; ++x) {
    setTimeout(() => console.log(x)) // closes over the `x` which is logically positioned at the top of the enclosing scope, above the loop
}
console.log(x) // note: visible outside the loop

ब्लॉक-स्कोप होने के undefinedकारण निम्नलिखित प्रिंट x। कॉलबैक एक-एक करके अतुल्यकालिक रूप से चलाए जाते हैं। के लिए नई व्यवहार letचर का मतलब है कि प्रत्येक गुमनाम समारोह नाम के एक अलग चर के ऊपर बंद कर दिया x(विपरीत इसके साथ किया होता var), और इसलिए पूर्णांकों 0के माध्यम से 4मुद्रित कर रहे हैं .:

for(let x = 0; x < 5; ++x) {
    setTimeout(() => console.log(x)) // `let` declarations are re-declared on a per-iteration basis, so the closures capture different variables
}
console.log(typeof x) // undefined

निम्नलिखित को नहीं फेंकेगा ReferenceErrorक्योंकि दृश्यता xब्लॉक द्वारा विवश नहीं है; हालाँकि, यह प्रिंट होगा undefinedक्योंकि वेरिएबल को इनिशियलाइज़ नहीं किया गया है ( ifस्टेटमेंट के कारण)।

if(false) {
    var x = 1
}
console.log(x) // here, `x` has been declared, but not initialised

forलूप के शीर्ष पर घोषित एक चर का उपयोग लूप letके शरीर के लिए किया जाता है:

for(let x = 0; x < 10; ++x) {} 
console.log(typeof x) // undefined, because `x` is block-scoped

निम्नलिखित को फेंक देगा ReferenceErrorक्योंकि दृश्यता xब्लॉक द्वारा विवश है:

if(false) {
    let x = 1
}
console.log(typeof x) // undefined, because `x` is block-scoped

उपयोग किए जाने वाले चर घोषित किए गए हैं var, letया constसभी मॉड्यूल के लिए स्कूप किए गए हैं:

// module1.js

var x = 0
export function f() {}

//module2.js

import f from 'module1.js'

console.log(x) // throws ReferenceError

निम्नलिखित वैश्विक वस्तु पर एक संपत्ति की घोषणा करेगा, क्योंकि वैरिएबल varको वैश्विक संदर्भ में उपयोग करने की घोषणा की जाती है, वैश्विक वस्तु के गुणों के रूप में जोड़े जाते हैं:

var x = 1
console.log(window.hasOwnProperty('x')) // true

letऔर constवैश्विक संदर्भ में वैश्विक ऑब्जेक्ट में गुण नहीं जोड़ते हैं, लेकिन अभी भी वैश्विक गुंजाइश है:

let x = 1
console.log(window.hasOwnProperty('x')) // false

फ़ंक्शन बॉडी में फंक्शन पैरामीटर घोषित किए जा सकते हैं:

function f(x) {}
console.log(typeof x) // undefined, because `x` is scoped to the function

कैच-ब्लॉक बॉडी के लिए कैच ब्लॉक पैरामीटर स्कोप किए गए हैं:

try {} catch(e) {}
console.log(typeof e) // undefined, because `e` is scoped to the catch block

नामित फ़ंक्शन एक्सप्रेशन को केवल एक्सप्रेशन पर स्कोप किया जाता है:

(function foo() { console.log(foo) })()
console.log(typeof foo) // undefined, because `foo` is scoped to its own expression

गैर-सख्त मोड में, वैश्विक वस्तु पर स्पष्ट रूप से परिभाषित गुण वैश्विक रूप से स्कोप किए जाते हैं। सख्त मोड में आपको एक त्रुटि मिलती है।

x = 1 // implicitly defined property on the global object (no "var"!)

console.log(x) // 1
console.log(window.hasOwnProperty('x')) // true

गैर-सख्त मोड में, फ़ंक्शन घोषणाओं में फ़ंक्शन गुंजाइश होती है। सख्त मोड में उनके पास ब्लॉक स्कोप है।

'use strict'
{
    function foo() {}
}
console.log(typeof foo) // undefined, because `foo` is block-scoped

यह हुड के नीचे कैसे काम करता है

स्कोप को कोड के शाब्दिक क्षेत्र के रूप में परिभाषित किया गया है जिसके ऊपर एक पहचानकर्ता मान्य है।

जावास्क्रिप्ट में, प्रत्येक फ़ंक्शन-ऑब्जेक्ट में एक छुपा [[Environment]]संदर्भ होता है जो निष्पादन संदर्भ (स्टैक फ्रेम) के शाब्दिक वातावरण का संदर्भ है जिसके भीतर इसे बनाया गया था।

जब आप किसी फ़ंक्शन का आह्वान करते हैं, तो छिपी हुई [[Call]]विधि को कहा जाता है। यह विधि एक नया निष्पादन संदर्भ बनाता है और नए निष्पादन संदर्भ और फ़ंक्शन-ऑब्जेक्ट के शाब्दिक वातावरण के बीच एक लिंक स्थापित करता है। यह [[Environment]]फ़ंक्शन-ऑब्जेक्ट पर मान को कॉपी करके , नए निष्पादन संदर्भ के शाब्दिक वातावरण पर एक बाहरी संदर्भ क्षेत्र में करता है।

ध्यान दें कि नए निष्पादन संदर्भ और फ़ंक्शन ऑब्जेक्ट के शाब्दिक वातावरण के बीच यह लिंक एक क्लोजर कहा जाता है ।

इस प्रकार, जावास्क्रिप्ट में, गुंजाइश को बाहरी संदर्भों द्वारा "श्रृंखला" में एक साथ जुड़े हुए शाब्दिक वातावरण के माध्यम से लागू किया जाता है। शाब्दिक वातावरण की इस श्रृंखला को स्कोप चेन कहा जाता है, और पहचानकर्ता रिज़ॉल्यूशन एक मेल पहचानकर्ता के लिए श्रृंखला की खोज करके होता है ।

पता लगाएँ कि अधिक


280
व्यापक होने के करीब भी नहीं है, लेकिन यह शायद जावास्क्रिप्ट दायरे चालों का पता होना चाहिए कि किसी को भी आधुनिक जावास्क्रिप्ट को प्रभावी ढंग से पढ़ने की जरूरत है।
त्रिपिटक

148
अत्यधिक मूल्यांकन किया गया उत्तर, निश्चित नहीं कि क्यों। यह उचित स्पष्टीकरण के बिना सिर्फ उदाहरणों का एक गुच्छा है, फिर प्रोटोटाइप श्रृंखला (यानी प्रॉपर्टी रिज़ॉल्यूशन) को गुंजाइश श्रृंखला (यानी चर रिज़ॉल्यूशन) के साथ भ्रमित करने के लिए लगता है। गुंजाइश और संपत्ति के संकल्प का एक व्यापक (और सटीक) स्पष्टीकरण comp.lang.javascript FAQ नोट्स में है
RobG

109
@RobG यह अत्यधिक मूल्यांकित किया गया है क्योंकि यह प्रोग्रामर की एक विस्तृत श्रृंखला के लिए उपयोगी और बोधगम्य है, लघु कैटचरेसिस के बावजूद। आपके द्वारा पोस्ट किया गया लिंक, जबकि कुछ पेशेवरों के लिए उपयोगी है, आज जावास्क्रिप्ट लिखने वाले अधिकांश लोगों के लिए समझ से बाहर है। उत्तर को संपादित करके किसी भी नाममात्र के मुद्दों को हल करने के लिए स्वतंत्र महसूस करें।
त्रिपिटक

7
@ triptych- मैं केवल छोटी चीज़ों को ठीक करने के लिए उत्तर संपादित करता हूं, प्रमुख नहीं। "गुंजाइश" को "संपत्ति" में बदलने से त्रुटि ठीक हो जाएगी, लेकिन बहुत स्पष्ट अंतर के बिना विरासत और दायरे को मिलाने का मुद्दा नहीं।
रॉबग

24
यदि आप बाहरी क्षेत्र में एक चर को परिभाषित करते हैं, और फिर एक बयान में फ़ंक्शन के अंदर एक चर को उसी नाम से परिभाषित करते हैं, भले ही अगर वह शाखा तक नहीं पहुंचता है तो इसे फिर से परिभाषित किया जाता है। एक उदाहरण - jsfiddle.net/3CxVm
क्रिस एस

233

जावास्क्रिप्ट किसी दिए गए फ़ंक्शन के लिए गुंजाइश स्थापित करने के लिए गुंजाइश श्रृंखलाओं का उपयोग करता है। आम तौर पर एक वैश्विक गुंजाइश है, और परिभाषित प्रत्येक फ़ंक्शन का अपना नेस्टेड गुंजाइश है। किसी अन्य फ़ंक्शन के भीतर परिभाषित किसी भी फ़ंक्शन में एक स्थानीय गुंजाइश होती है जो बाहरी फ़ंक्शन से जुड़ी होती है। यह हमेशा उस स्रोत की स्थिति है जो दायरे को परिभाषित करता है।

स्कोप श्रृंखला में एक तत्व मूल रूप से एक मैप है जिसका पॉइंटर अपने मूल स्कोप के साथ है।

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


1
स्कोप चेन [मेमोरी] क्लोजर्स के लिए एक और शब्द है ... जो पढ़ने के लिए यहाँ हैं / जावास्क्रिप्ट में जानने के लिए।
न्यू अलेक्जेंड्रिया

108

वैश्विक स्तर पर घोषित चर में वैश्विक गुंजाइश होती है। किसी फ़ंक्शन के भीतर घोषित चर को उस फ़ंक्शन पर स्कोप किया जाता है, और उसी नाम के वैश्विक वैरिएबल्स को छायांकित किया जाता है।

(मुझे यकीन है कि कई सूक्ष्मताएं हैं जो वास्तविक जावास्क्रिप्ट प्रोग्रामर अन्य उत्तरों में इंगित करने में सक्षम होंगे। विशेष रूप से मैं इस पृष्ठ पर आया हूं कि thisकिसी भी समय वास्तव में इसका क्या मतलब है। उम्मीद है कि यह अधिक परिचयात्मक लिंक आपको शुरू करने के लिए पर्याप्त है। ।)


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

10
@ ट्रीपिक: मुझे पता है कि आपके हाथ से निकलने वाली चीजों के बारे में आपका क्या मतलब है, लेकिन कृपया किसी भी तरह एक उत्तर जोड़ें। मुझे उपरोक्त कुछ खोजों से मिला ... वास्तविक अनुभव वाले किसी व्यक्ति द्वारा लिखा गया उत्तर बेहतर होने के लिए बाध्य है। कृपया मेरे किसी भी उत्तर को सही करें जो निश्चित रूप से गलत है!
जॉन स्कीट

4
किसी तरह जॉन स्केट स्टैक ओवरफ्लो पर मेरे सबसे लोकप्रिय जवाब के लिए जिम्मेदार है।
त्रिपिटक

75

पुराने स्कूल जावास्क्रिप्ट

परंपरागत रूप से, जावास्क्रिप्ट में वास्तव में केवल दो प्रकार के क्षेत्र हैं:

  1. ग्लोबल स्कोप : वेरिएबल्स को आवेदन की शुरुआत से ( पूरे) में जाना जाता है (*)
  2. फंक्शनल स्कोप : वेरिएबल्स फ़ंक्शन के भीतर जाने जाते हैं जिन्हें वे फंक्शन की शुरुआत से घोषित करते हैं (*)

मैं इस बारे में विस्तार से नहीं बताऊंगा, क्योंकि पहले से ही कई अन्य उत्तर हैं जो अंतर की व्याख्या कर रहे हैं।


आधुनिक जावास्क्रिप्ट

सबसे हाल ही में जावास्क्रिप्ट चश्मा अब भी एक तिहाई गुंजाइश अनुमति देते हैं:

  1. ब्लॉक स्कोप : पहचानकर्ताओं को उनके द्वारा घोषित दायरे के ऊपर से "ज्ञात" किया जाता है , लेकिन उनकी घोषणा के बाद तक उन्हें (डीआरई) नहीं दिया जा सकता। इस अंतरिम अवधि को "अस्थायी मृत क्षेत्र" कहा जाता है।

मैं ब्लॉक स्कोप वैरिएबल कैसे बनाऊं?

परंपरागत रूप से, आप इस तरह अपने चर बनाते हैं:

var myVariable = "Some text";

ब्लॉक स्कोप वैरिएबल इस तरह बनाए जाते हैं:

let myVariable = "Some text";

तो फ़ंक्शनल स्कोप और ब्लॉक स्कोप में क्या अंतर है?

कार्यात्मक गुंजाइश और ब्लॉक गुंजाइश के बीच अंतर को समझने के लिए, निम्नलिखित कोड पर विचार करें:

// i IS NOT known here
// j IS NOT known here
// k IS known here, but undefined
// l IS NOT known here

function loop(arr) {
    // i IS known here, but undefined
    // j IS NOT known here
    // k IS known here, but has a value only the second time loop is called
    // l IS NOT known here

    for( var i = 0; i < arr.length; i++ ) {
        // i IS known here, and has a value
        // j IS NOT known here
        // k IS known here, but has a value only the second time loop is called
        // l IS NOT known here
    };

    // i IS known here, and has a value
    // j IS NOT known here
    // k IS known here, but has a value only the second time loop is called
    // l IS NOT known here

    for( let j = 0; j < arr.length; j++ ) {
        // i IS known here, and has a value
        // j IS known here, and has a value
        // k IS known here, but has a value only the second time loop is called
        // l IS NOT known here
    };

    // i IS known here, and has a value
    // j IS NOT known here
    // k IS known here, but has a value only the second time loop is called
    // l IS NOT known here
}

loop([1,2,3,4]);

for( var k = 0; k < arr.length; k++ ) {
    // i IS NOT known here
    // j IS NOT known here
    // k IS known here, and has a value
    // l IS NOT known here
};

for( let l = 0; l < arr.length; l++ ) {
    // i IS NOT known here
    // j IS NOT known here
    // k IS known here, and has a value
    // l IS known here, and has a value
};

loop([1,2,3,4]);

// i IS NOT known here
// j IS NOT known here
// k IS known here, and has a value
// l IS NOT known here

यहां, हम देख सकते हैं कि हमारा वेरिएबल jकेवल पहले लूप के लिए जाना जाता है, लेकिन पहले और बाद में नहीं। फिर भी, हमारे चर iपूरे समारोह में जाना जाता है।

इसके अलावा, विचार करें कि ब्लॉक किए गए चरों को घोषित किए जाने से पहले ज्ञात नहीं किया जाता है क्योंकि वे फहराए नहीं जाते हैं। आपको उसी ब्लॉक के भीतर उसी ब्लॉक किए गए वैरिएबल वैरिएबल को फिर से भेजने की भी अनुमति नहीं है। यह ब्लॉक स्कॉप्ड वेरिएबल्स को वैश्विक या कार्यात्मक रूप से स्कॉप किए गए वेरिएबल की तुलना में कम त्रुटि वाला बनाता है, जो फहराए जाते हैं और जो कई घोषणाओं के मामले में कोई त्रुटि उत्पन्न नहीं करते हैं।


क्या आज ब्लॉक स्कोप वैरिएबल का उपयोग करना सुरक्षित है?

आज उपयोग करना सुरक्षित है या नहीं, यह आपके पर्यावरण पर निर्भर करता है:

  • यदि आप सर्वर-साइड जावास्क्रिप्ट कोड ( Node.js ) लिख रहे हैं , तो आप सुरक्षित रूप से letस्टेटमेंट का उपयोग कर सकते हैं ।

  • आप क्लाइंट-साइड जावास्क्रिप्ट कोड लिखने और एक ब्राउज़र आधारित transpiler (तरह का उपयोग कर रहे हैं तो Traceur या कोलाहल-स्टैंडअलोन ), आप सुरक्षित रूप से उपयोग कर सकते हैं let, बयान हालांकि, अपने कोड की संभावना प्रदर्शन के संबंध में कुछ भी लेकिन इष्टतम हो रहा है।

  • यदि आप क्लाइंट-साइड जावास्क्रिप्ट कोड लिख रहे हैं और नोड आधारित ट्रांसपाइलर (जैसे ट्रेसेल शेल स्क्रिप्ट या बैबेल ) का उपयोग कर रहे हैं, तो आप सुरक्षित रूप से letस्टेटमेंट का उपयोग कर सकते हैं । और क्योंकि आपके ब्राउज़र को केवल ट्रांसप्लड कोड के बारे में पता होगा, प्रदर्शन कमियां सीमित होनी चाहिए।

  • यदि आप क्लाइंट-साइड जावास्क्रिप्ट कोड लिख रहे हैं और ट्रांसपिलर का उपयोग नहीं करते हैं, तो आपको ब्राउज़र समर्थन पर विचार करने की आवश्यकता है।

    ये कुछ ब्राउज़र हैं जो बिल्कुल भी समर्थन नहीं करते letहैं:

    • इंटरनेट एक्सप्लोरर 10 और नीचे
    • फ़ायरफ़ॉक्स 43 और नीचे
    • सफारी 9 और नीचे
    • Android ब्राउज़र 4 और नीचे
    • ओपेरा 27 और नीचे
    • चोम 40 और नीचे
    • ओपेरा मिनी और ब्लैकबेरी ब्राउज़र का कोई भी संस्करण

यहां छवि विवरण दर्ज करें


ब्राउज़र समर्थन का ट्रैक कैसे रखें

अद्यतित अवलोकन के लिए कौन से ब्राउज़र letइस उत्तर को पढ़ने के समय कथन का समर्थन करते हैं, यह Can I Useपृष्ठ देखें ।


(*) ग्लोबली और फंक्शनलली स्कॉप्ड वैरिएबल्स को इनिशियलाइज़ किया जा सकता है और इन्हें घोषित किए जाने से पहले इस्तेमाल किया जा सकता है क्योंकि जावास्क्रिप्ट वेरिएबल्स को फहराया जाता हैइसका मतलब है कि घोषणाएं हमेशा गुंजाइश के शीर्ष पर होती हैं।


2
"नहीं जाना जाता है" भ्रामक है, क्योंकि परिवर्तनशील होने के कारण चर घोषित किया जाता है।
ओरियल

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

1
यह मददगार था, धन्यवाद! मुझे लगता है कि "मॉडर्न जावास्क्रिप्ट" और "ओल्ड स्कूल जावास्क्रिप्ट" से आपका जो मतलब है, उसके बारे में विशिष्ट होना और भी अधिक उपयोगी होगा; मुझे लगता है कि ये ECMAScript 6 / ES6 / ECMAScript 2015 और पहले के संस्करणों से क्रमशः मेल खाते हैं?
जॉन श्नाइडर

1
@JonSchneider: सही है! जहां मैं "पुराने स्कूल जावास्क्रिप्ट" कहता हूं, मैं ईसीएमएस्क्रिप्ट 5 के बारे में बात कर रहा हूं और जहां मैं "आधुनिक जावास्क्रिप्ट" का उल्लेख कर रहा हूं, मैं ECMAScript 6 (उर्फ ECMAScript 2015) के बारे में ले रहा हूं। मुझे नहीं लगा कि यह वास्तव में यहाँ पर विस्तार से जाना महत्वपूर्ण है, हालांकि, जैसा कि ज्यादातर लोग जानना चाहते हैं (1) ब्लॉक स्कोप और कार्यात्मक गुंजाइश के बीच अंतर क्या है, (2) क्या ब्राउज़र ब्लॉक स्कोप और (3) का समर्थन करते हैं चाहे वे जिस भी प्रोजेक्ट पर काम कर रहे हों, उसके लिए आज ब्लॉक स्कोप का इस्तेमाल करना सुरक्षित हो। इसलिए मैंने उन मुद्दों को संबोधित करने पर अपना जवाब केंद्रित किया।
जॉन सेलर्स

1
@JonSchneider: (जारी) इसके बावजूद, मैंने अभी उन लोगों के लिए ES6 / ES2015 पर एक स्मैशिंग मैगज़ीन लेख का लिंक जोड़ा है, जो उन लोगों के बारे में अधिक जानना चाहते हैं, जिन्होंने पिछले कुछ वर्षों के दौरान जावास्क्रिप्ट में कुछ सुविधाएँ जोड़ी हैं ... जो किसी और की सोच रहा होगा कि "आधुनिक जावास्क्रिप्ट" से मेरा क्या मतलब है।
जॉन सलेगर्स

39

यहाँ एक उदाहरण है:

<script>

var globalVariable = 7; //==window.globalVariable

function aGlobal( param ) { //==window.aGlobal(); 
                            //param is only accessible in this function
  var scopedToFunction = {
    //can't be accessed outside of this function

    nested : 3 //accessible by: scopedToFunction.nested
  };

  anotherGlobal = {
    //global because there's no `var`
  }; 

}

</script>

आप क्लोज़र की जांच करना चाहते हैं, और निजी सदस्यों को बनाने के लिए उनका उपयोग कैसे करें ।



26

"जावास्क्रिप्ट 1.7" में (जावास्क्रिप्ट के लिए मोज़िला का विस्तार) एक भी letबयान के साथ ब्लॉक-स्कोप चर घोषित कर सकता है :

 var a = 4;
 let (a = 3) {
   alert(a); // 3
 }
 alert(a);   // 4

2
हाँ, लेकिन यह उपयोग करने के लिए सुरक्षित है? मेरा मतलब है कि यदि मेरा कोड WebKit में चलेगा, तो क्या मैं वास्तव में इस कार्यान्वयन को चुनूंगा?
इगोरगानापोलस्की

10
@ अजगर: नहीं, WebKit समर्थन नहीं करता है let
kennytm

मुझे लगता है कि इसके लिए एकमात्र वैध उपयोग होगा यदि आप जानते हैं कि सभी क्लाइंट एक मोज़िला ब्राउज़र का उपयोग कर रहे होंगे जैसे कि एक कंपनी आंतरिक प्रणाली।
गज़ब

या अगर आप XUL फ्रेमवर्क, मोज़िला के इंटरफ़ेस फ्रेमवर्क का उपयोग करके प्रोग्रामिंग कर रहे हैं, जहाँ आप css, xml और जावास्क्रिप्ट का उपयोग कर निर्माण करते हैं।
जेरार्ड ओनील

1
@ गज़ब भी एक भयावह विचार है! इसलिए आज आप जानते हैं कि आपके ग्राहक मोज़िला का उपयोग कर रहे हैं, तो एक नया मेमो आता है जिसमें कहा गया है कि अब वे कुछ और उपयोग कर रहे हैं। IE कारण हमारे भुगतान प्रणाली बेकार है ... आप IE8 और कभी IE9 या IE10 या फ़ायरफ़ॉक्स या क्रोम का उपयोग नहीं करना चाहिए क्योंकि यह फ्लैट काम नहीं करेगा ...
buzzsawddog

25

मूल रूप से ब्रेंडन ईच द्वारा डिजाइन किए जाने पर जावास्क्रिप्ट में स्कोपिंग का विचार हाइपरकार्ड स्क्रिप्टिंग भाषा हाइपरटॉक से आया है ।

इस भाषा में, डिस्प्ले इंडेक्स कार्ड्स के ढेर के समान किए गए थे। पृष्ठभूमि के रूप में संदर्भित एक मास्टर कार्ड था। यह पारदर्शी था और इसे निचले कार्ड के रूप में देखा जा सकता है। इस आधार कार्ड की कोई भी सामग्री इसके शीर्ष पर रखे गए कार्डों के साथ साझा की गई थी। शीर्ष पर रखे गए प्रत्येक कार्ड की अपनी सामग्री होती थी जो पिछले कार्ड की तुलना में पूर्वता लेती थी, लेकिन वांछित होने पर भी पूर्व कार्ड तक पहुंच थी।

यह वास्तव में जावास्क्रिप्ट स्कूपिंग सिस्टम कैसे बनाया गया है। इसके बस अलग-अलग नाम हैं। जावास्क्रिप्ट में कार्ड एक्ज़ीक्यूशन कॉन्टेक्ट्स ECMA के रूप में जाने जाते हैं । इनमें से हर एक संदर्भ में तीन मुख्य भाग होते हैं। एक चर वातावरण, एक शाब्दिक वातावरण, और यह एक बाध्यकारी है। कार्ड के संदर्भ में वापस जा रहे हैं, लेक्सिकल वातावरण में स्टैक में निचले कार्ड से पहले की सभी सामग्री शामिल है। वर्तमान संदर्भ स्टैक के शीर्ष पर है और वहां घोषित किसी भी सामग्री को चर वातावरण में संग्रहीत किया जाएगा। नामकरण टकराव के मामले में चर वातावरण पूर्वता लेगा।

यह बंधन युक्त वस्तु को इंगित करेगा। कभी-कभी स्कोप्स या एक्ज़ीक्यूशन कॉन्टेक्ट्स बिना ऑब्जेक्ट को बदले हुए बदल जाते हैं, जैसे कि एक घोषित फंक्शन में जिसमें सम्‍मिलित ऑब्जेक्ट windowया कंस्‍ट्रक्‍टर फंक्शन हो सकता है।

ये निष्पादन संदर्भ किसी भी समय नियंत्रण बनाए जाने पर बनाए जाते हैं। जब कोड निष्पादित करना शुरू हो जाता है तो नियंत्रण स्थानांतरित हो जाता है, और यह मुख्य रूप से फ़ंक्शन निष्पादन से होता है।

तो वह तकनीकी व्याख्या है। व्यवहार में, यह याद रखना महत्वपूर्ण है कि जावास्क्रिप्ट में

  • स्कोप तकनीकी रूप से "एक्ज़ीक्यूटिव कॉन्क्लेट्स" हैं
  • कॉन्टेक्ट्स उन वातावरणों का एक समूह बनाते हैं जहां चर संग्रहित होते हैं
  • स्टैक का शीर्ष पूर्वता लेता है (नीचे वैश्विक संदर्भ है)
  • प्रत्येक फ़ंक्शन एक निष्पादन संदर्भ बनाता है (लेकिन हमेशा एक नया यह बंधन नहीं)

इस पृष्ठ पर पिछले उदाहरणों में से एक (5. "क्लोजर") पर लागू करना, निष्पादन संदर्भों के ढेर का पालन करना संभव है। इस उदाहरण में स्टैक में तीन संदर्भ हैं। वे बाहरी संदर्भ द्वारा परिभाषित होते हैं, प्रसंग को तुरंत छः द्वारा बुलाए गए फ़ंक्शन में संदर्भ, और छः के तुरंत आहरण समारोह के अंदर लौटे फ़ंक्शन में संदर्भ को संदर्भित किया जाता है।

i ) बाहरी संदर्भ। इसमें एक = 1
ii का एक चर वातावरण है । IIFE संदर्भ, इसमें = 1 का एक शाब्दिक वातावरण है, लेकिन a = 6 का चर वातावरण जो स्टैक में पूर्ववर्तीता लेता है
iii ) लौटाया गया फ़ंक्शन संदर्भ, इसमें एक शब्दांश है। a = 6 का वातावरण और कहा जाने पर चेतावनी में संदर्भित मान है।

यहां छवि विवरण दर्ज करें


17

1) एक वैश्विक गुंजाइश है, एक फंक्शन स्कोप है, और स्कोप के साथ और कैच है। वेरिएबल के साथ - और कैच स्टेटमेंट में उनके ब्लॉक में नाम जोड़ने के लिए सामान्य रूप से कोई 'ब्लॉक' स्तर गुंजाइश नहीं है।

2) कार्यक्षेत्रों द्वारा वैश्विक दायरे में सभी तरह से घोंसले का शिकार किया जाता है।

3) प्रॉपर्टी को प्रोटोटाइप चेन से गुज़रते हुए हल किया जाता है। कथन के साथ ब्लॉक के साथ परिभाषित लेक्सिकल स्कोप में ऑब्जेक्ट प्रॉपर्टी के नाम सामने आते हैं।

संपादित करें: ECMAAScript 6 (सद्भाव) का समर्थन करने के लिए युक्ति है, और मुझे पता है कि क्रोम एक 'सद्भाव' ध्वज की अनुमति देता है, इसलिए शायद यह इसका समर्थन करता है।

आज्ञा देना ब्लॉक स्तर के स्कोपिंग के लिए एक समर्थन होगा, लेकिन आपको ऐसा करने के लिए कीवर्ड का उपयोग करना होगा।

EDIT: बेंजामिन के साथ इशारा करने और टिप्पणियों में बयान पकड़ने के आधार पर, मैंने पोस्ट को संपादित किया है, और अधिक जोड़ा है। दोनों के साथ और कैच स्टेटमेंट अपने संबंधित ब्लॉकों में चर पेश करते हैं, और यह एक ब्लॉक गुंजाइश है। इन चरों को उनमें पारित वस्तुओं के गुणों के लिए अलियास किया जाता है।

 //chrome (v8)

 var a = { 'test1':'test1val' }
 test1   // error not defined
 with (a) { var test1 = 'replaced' }
 test1   // undefined
 a       // a.test1 = 'replaced'

संपादित करें: स्पष्ट उदाहरण:

test1 ब्लॉक के साथ स्कोप किया जाता है, लेकिन a.test1 को अलियास किया जाता है। 'Var test1' ऊपरी शाब्दिक संदर्भ (फ़ंक्शन, या वैश्विक) में एक नया वैरिएबल test1 बनाता है, जब तक कि यह एक संपत्ति नहीं है - जो कि यह है।

ओह! 'के साथ' का उपयोग करते समय सावधान रहें - जैसे कि var एक नूप है यदि वैरिएबल पहले से ही फ़ंक्शन में परिभाषित किया गया है, तो यह ऑब्जेक्ट से आयात किए गए नामों के संबंध में भी एक noop है! पहले से ही परिभाषित किया जा रहा नाम पर एक छोटे से सिर यह बहुत सुरक्षित होगा। मैं व्यक्तिगत रूप से इसका उपयोग कभी नहीं करूंगा।


आपके यहाँ कुछ गलतियाँ हैं, एक जावास्क्रिप्ट के लिए ब्लॉक स्कूपिंग के रूप हैं।
बेंजामिन ग्रुएनबाम

मेरे कान (आंखें) खुले हैं, बेंजामिन - ऊपर मेरे बयान हैं कि मैं कैसे जावास्क्रिप्ट स्कूपिंग का इलाज कर रहा हूं, लेकिन वे कल्पना पढ़ने पर आधारित नहीं हैं। और मुझे आशा है कि आप कथन (जो कि वस्तु का एक रूप है) का उल्लेख नहीं कर रहे हैं, या मोज़िला का विशेष वाक्य 'वाक्य' है।
जेरार्ड ओनील

खैर, withस्टेटमेंट ब्लॉक स्कूपिंग का एक रूप है, लेकिन catchक्लॉज़ एक बहुत अधिक सामान्य रूप हैं (मज़ेदार तथ्य, v8 के catchसाथ कार्यान्वयन with)) - यह जावास्क्रिप्ट में ही ब्लॉक स्कूपिंग के एकमात्र रूप हैं (जो कि फंक्शन, ग्लोबल, ट्राइ या कैच हैं) , और उनके डेरिवेटिव के साथ), हालांकि मेजबान वातावरण में स्कूपिंग की अलग-अलग धारणाएं हैं - उदाहरण के लिए ब्राउज़र में इनलाइन घटनाओं और एनओडीजेएस के वीएम मॉड्यूल।
बेंजामिन ग्रुएनबाम

बेंजामिन - जो मैं देख सकता हूं, दोनों के साथ और पकड़ केवल वस्तु को वर्तमान दायरे (और इस तरह के गुण) में पेश करते हैं, लेकिन फिर संबंधित ब्लॉक समाप्त होने के बाद, चर रीसेट हो जाते हैं। लेकिन उदाहरण के लिए, कैच में पेश किए गए एक नए वेरिएबल में एनक्लोजिंग फंक्शन / मेथड का स्कोप होगा।
गेरार्ड ओनील

2
जो वास्तव में ब्लॉक स्कूपिंग का मतलब है :)
बेंजामिन Gruenbaum

9

मैंने पाया कि जावास्क्रिप्ट में नए लोगों को यह समझने में परेशानी होती है कि विरासत में डिफ़ॉल्ट रूप से भाषा में उपलब्ध है और फ़ंक्शन फंक्शन स्कोप ही एकमात्र स्कोप है। मैंने JSPretty नामक एक ब्यूटीफायर को पिछले साल के अंत में एक एक्सटेंशन प्रदान किया था। फीचर रंग कोड में कार्यक्षेत्र गुंजाइश रखते हैं और हमेशा उस दायरे में घोषित सभी चर के लिए एक रंग जोड़ते हैं। क्लोजर को नेत्रहीन रूप से प्रदर्शित किया जाता है, जब एक दायरे से एक रंग के साथ एक चर एक अलग दायरे में उपयोग किया जाता है।

पर सुविधा का प्रयास करें:

पर एक डेमो देखें:

यहां देखें कोड:

वर्तमान में यह सुविधा 16 नेस्टेड फ़ंक्शन की गहराई के लिए समर्थन प्रदान करती है, लेकिन वर्तमान में वैश्विक चर को रंग नहीं देती है।


1
फ़ायरफ़ॉक्स 26 के साथ मेरे लिए काम नहीं करता है। मैं कोड पेस्ट करता हूं या फ़ाइल लोड करता हूं, निष्पादन पर क्लिक करता हूं और कुछ भी नहीं होता है।
mplwork

स्कोप और इनहेरिटेंस दो अंतर चीजें हैं।
बेन एस्टन

9

जावास्क्रिप्ट में केवल दो प्रकार के क्षेत्र हैं:

  1. ग्लोबल स्कोप : ग्लोबल एक विंडो लेवल स्कोप के अलावा और कुछ नहीं है। पूरे एप्लिकेशन में मौजूद वेरिएबल।
  2. कार्यात्मक स्कोप : varकीवर्ड के साथ एक फ़ंक्शन के भीतर घोषित परिवर्तनीय में कार्यात्मक गुंजाइश है।

जब भी किसी फ़ंक्शन को बुलाया जाता है, तो एक चर गुंजाइश ऑब्जेक्ट बनाई जाती है (और गुंजाइश श्रृंखला में शामिल होती है) जो जावास्क्रिप्ट में चर के बाद होती है।

        a = "global";
         function outer(){ 
              b = "local";
              console.log(a+b); //"globallocal"
         }
outer();

स्कोप श्रृंखला ->

  1. विंडो स्तर - aऔर outerफ़ंक्शन स्कोप श्रृंखला में शीर्ष स्तर पर हैं।
  2. जब बाहरी फ़ंक्शन को एक नया variable scope object(और कार्यक्षेत्र श्रृंखला में शामिल) कहा जाता bहै, तो इसके अंदर चर के साथ जोड़ा जाता है।

अब जब एक चर की aआवश्यकता होती है तो यह पहले निकटतम चर दायरे की खोज करता है और यदि चर नहीं है तो यह चर गुंजाइश श्रृंखला की अगली वस्तु की ओर जाता है। जो इस मामले में विंडो स्तर है।


1
निश्चित नहीं कि यह स्वीकृत उत्तर क्यों नहीं है। वास्तव में सिर्फ कार्यात्मक गुंजाइश है (ईसीएमए 6 से पहले कोई "स्थानीय गुंजाइश" नहीं थी) और वैश्विक बाइंडिंग
टेक्ससब्रस

9

अन्य उत्तरों में जोड़ने के लिए, स्कोप सभी घोषित पहचानकर्ताओं (चर) की एक लुक-अप सूची है, और नियमों का एक सख्त सेट लागू करता है कि ये वर्तमान में कोड निष्पादित करने के लिए कैसे सुलभ हैं। यह लुक-अप वैरिएबल को असाइन करने के उद्देश्यों के लिए हो सकता है, जो एक LHS (लेफ्टहैंड-साइड) संदर्भ है, या यह इसके मूल्य को पुनः प्राप्त करने के उद्देश्यों के लिए हो सकता है, जो कि RHS (राइटहैंड-साइड) संदर्भ है। ये लुक-अप वही हैं जो जावास्क्रिप्ट इंजन आंतरिक रूप से कर रहा है जब यह कोड को संकलित और निष्पादित कर रहा है।

इसलिए इस दृष्टिकोण से, मुझे लगता है कि एक तस्वीर से मुझे काइल सिम्पसन द्वारा स्कोप और क्लोज़र ईबुक में मदद मिलेगी:

छवि

उनके ebook से उद्धरण:

इमारत हमारे कार्यक्रम के नेस्टेड स्कोप नियम का प्रतिनिधित्व करती है। इमारत की पहली मंजिल आपके वर्तमान में निष्पादित गुंजाइश का प्रतिनिधित्व करती है, चाहे आप कहीं भी हों। भवन का शीर्ष स्तर वैश्विक क्षेत्र है। आप अपनी वर्तमान मंजिल को देखते हुए LHS और RHS संदर्भों को हल करते हैं, और यदि आप इसे नहीं पाते हैं, तो लिफ्ट को अगली मंजिल पर ले जाते हुए, फिर वहाँ, फिर अगले और इसी तरह से देखते हैं। एक बार जब आप शीर्ष मंजिल (वैश्विक दायरे) में पहुंच जाते हैं, तो आप या तो वही पाते हैं जो आप खोज रहे हैं, या आप नहीं। लेकिन आपको परवाह किए बिना रुकना होगा।

ध्यान देने वाली एक बात जो ध्यान देने योग्य है, "स्कोप लुक-अप रुक जाता है क्योंकि यह पहला मैच पाता है"।

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


8

कोड चलाएँ। आशा है कि यह स्कूपिंग के बारे में एक विचार देगा

Name = 'global data';
document.Name = 'current document data';
(function(window,document){
var Name = 'local data';
var myObj = {
    Name: 'object data',
    f: function(){
        alert(this.Name);
    }
};

myObj.newFun = function(){
    alert(this.Name);
}

function testFun(){
    alert("Window Scope : " + window.Name + 
          "\nLocal Scope : " + Name + 
          "\nObject Scope : " + this.Name + 
          "\nCurrent document Scope : " + document.Name
         );
}


testFun.call(myObj);
})(window,document);

8

वैश्विक कार्यक्षेत्र :

वैश्विक चर बिल्कुल वैश्विक सितारों (जैकी चैन, नेल्सन मंडेला) की तरह हैं। आप अपने एप्लिकेशन के किसी भी भाग से उन्हें (मान प्राप्त या सेट कर सकते हैं) एक्सेस कर सकते हैं। वैश्विक कार्य वैश्विक घटनाओं (नव वर्ष, क्रिसमस) की तरह हैं। आप उन्हें अपने आवेदन के किसी भी भाग से निष्पादित (कॉल) कर सकते हैं।

//global variable
var a = 2;

//global function
function b(){
   console.log(a);  //access global variable
}

स्थानीय स्कोप:

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

स्थानीय चर स्थानीय सितारों की तरह होते हैं। आप केवल दायरे के अंदर उन्हें (मान प्राप्त या सेट कर सकते हैं) एक्सेस कर सकते हैं। एक स्थानीय फ़ंक्शन स्थानीय घटनाओं की तरह होता है - आप उस दायरे में केवल (जश्न मना सकते हैं) निष्पादित कर सकते हैं। यदि आप उन्हें दायरे से बाहर एक्सेस करना चाहते हैं, तो आपको एक संदर्भ त्रुटि मिलेगी

function b(){
   var d = 21; //local variable
   console.log(d);

   function dog(){  console.log(a); }
     dog(); //execute local function
}

 console.log(d); //ReferenceError: dddddd is not defined    

कार्यक्षेत्र की गहन समझ के लिए इस लेख को देखें


6

ALMOST केवल दो प्रकार के जावास्क्रिप्ट स्कोप हैं:

  • प्रत्येक var घोषणा का दायरा सबसे तुरंत संलग्न फ़ंक्शन के साथ जुड़ा हुआ है
  • अगर किसी var घोषणा के लिए कोई एनक्लोजिंग फ़ंक्शन नहीं है, तो यह वैश्विक गुंजाइश है

इसलिए, फ़ंक्शंस के अलावा कोई भी ब्लॉक नया स्कोप नहीं बनाता है। यह बताता है कि बाहरी छोरों वाले चर को अधिलेखित करने के लिए लूप क्यों:

var i = 10, v = 10;
for (var i = 0; i < 5; i++) { var v = 5; }
console.log(i, v);
// output 5 5

इसके बजाय कार्यों का उपयोग करना:

var i = 10, v = 10;
$.each([0, 1, 2, 3, 4], function(i) { var v = 5; });
console.log(i,v);
// output 10 10

पहले उदाहरण में, कोई ब्लॉक स्कोप नहीं था, इसलिए शुरू में घोषित चर ओवरराइट किए गए थे। दूसरे उदाहरण में, फ़ंक्शन के कारण एक नया स्कोप था, इसलिए शुरू में घोषित किए गए चर SHADOWED थे, और ओवरराइट नहीं किए गए थे।

जावास्क्रिप्ट स्कूपिंग के संदर्भ में आपको बस इतना ही जानना चाहिए:

  • नए स्कोप को शुरू / पकड़ने का प्रयास करें केवल अपवाद चर के लिए ही, अन्य चर में नया स्कोप नहीं है
  • के साथ-जाहिरा तौर पर एक और अपवाद है, लेकिन इसका उपयोग करने वाले खंड के साथ अत्यधिक हतोत्साहित किया गया है ( https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/with )

तो आप देख सकते हैं कि जावास्क्रिप्ट स्कूपिंग वास्तव में बेहद सरल है, यद्यपि हमेशा सहज नहीं है। कुछ बातों के बारे में पता होना चाहिए:

  • var घोषणाएँ गुंजाइश के शीर्ष पर फहराई जाती हैं। इसका मतलब यह है कि संकलक के लिए कोई फर्क नहीं पड़ता कि यह कहां होता है, यह वैसा ही है जैसे कि वर स्वयं शीर्ष पर होता है
  • एक ही दायरे के भीतर कई var घोषणाएं संयुक्त हैं

तो यह कोड:

var i = 1;
function abc() {
  i = 2;
  var i = 3;
}
console.log(i);     // outputs 1

के बराबर है:

var i = 1;
function abc() {
  var i;     // var declaration moved to the top of the scope
  i = 2;
  i = 3;     // the assignment stays where it is
}
console.log(i);

यह काउंटर सहज लग सकता है, लेकिन यह एक अनिवार्य भाषा डिजाइनर के दृष्टिकोण से समझ में आता है।


5

आधुनिक जेएस, ईएस 6 +, ' const' और ' let'

आपको अपने द्वारा बनाए जाने वाले प्रत्येक चर के लिए ब्लॉक स्कूपिंग का उपयोग करना चाहिए, जैसे कि अन्य प्रमुख भाषाओं की तरह। varहै अप्रचलित । यह आपके कोड को सुरक्षित और अधिक रखरखाव योग्य बनाता है।

const95% मामलों के लिए इस्तेमाल किया जाना चाहिए । यह बनाता है ताकि चर संदर्भ बदल नहीं सके। सरणी, ऑब्जेक्ट और DOM नोड गुण बदल सकते हैं और होने की संभावना होनी चाहिए const

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

ब्लॉक स्कोप का मतलब है कि चर केवल उस ब्रैकेट के भीतर उपलब्ध होगा जिसमें यह घोषित किया गया है। यह आंतरिक दायरे में फैली हुई है, जिसमें आपके कार्यक्षेत्र के भीतर निर्मित अनाम फ़ंक्शंस भी शामिल हैं।


3

इस जिज्ञासु उदाहरण का प्रयास करें। नीचे दिए गए उदाहरण में यदि कोई अंक 0 पर आरंभिक था, तो आप 0 देखेंगे और फिर 1. एक वस्तु को छोड़कर और जावास्क्रिप्ट इसकी एक प्रति के बजाय f1 के एक सूचक को पास करेगा। इसका परिणाम यह होता है कि आपको दोनों समय एक ही चेतावनी मिलती है।

var a = new Date();
function f1(b)
{
    b.setDate(b.getDate()+1);
    alert(b.getDate());
}
f1(a);
alert(a.getDate());

3

जेएस में केवल फ़ंक्शन स्कोप हैं। स्कोप को ब्लॉक न करें! आप देख सकते हैं कि क्या फहरा रहा है।

var global_variable = "global_variable";
var hoisting_variable = "global_hoist";

// Global variables printed
console.log("global_scope: - global_variable: " + global_variable);
console.log("global_scope: - hoisting_variable: " + hoisting_variable);

if (true) {
    // The variable block will be global, on true condition.
    var block = "block";
}
console.log("global_scope: - block: " + block);

function local_function() {
    var local_variable = "local_variable";
    console.log("local_scope: - local_variable: " + local_variable);
    console.log("local_scope: - global_variable: " + global_variable);
    console.log("local_scope: - block: " + block);
    // The hoisting_variable is undefined at the moment.
    console.log("local_scope: - hoisting_variable: " + hoisting_variable);

    var hoisting_variable = "local_hoist";
    // The hoisting_variable is now set as a local one.
    console.log("local_scope: - hoisting_variable: " + hoisting_variable);
}

local_function();

// No variable in a separate function is visible into the global scope.
console.log("global_scope: - local_variable: " + local_variable);

(उत्तर पोस्ट किए जाने के बाद लंबे समय तक) ब्लॉक गुंजाइश; developer.mozilla.org/en/docs/Web/JavaScript/Reference/…
बॉब

2

मेरी समझ यह है कि 3 स्कोप हैं: वैश्विक गुंजाइश, वैश्विक रूप से उपलब्ध; स्थानीय गुंजाइश, ब्लॉक की परवाह किए बिना एक पूरे समारोह के लिए उपलब्ध; और ब्लॉक स्कोप, केवल उस ब्लॉक, स्टेटमेंट या एक्सप्रेशन पर उपलब्ध है, जिस पर इसका उपयोग किया गया था। ग्लोबल और लोकल स्कोप को 'var' कीवर्ड के साथ संकेत दिया जाता है, या तो फंक्शन या बाहर, और ब्लॉक स्कोप को 'let' कीवर्ड के साथ दर्शाया जाता है।

उन लोगों के लिए जो मानते हैं कि केवल वैश्विक और स्थानीय गुंजाइश है, कृपया बताएं कि मोज़िला के पास जेएस में ब्लॉक गुंजाइश की बारीकियों का वर्णन करने वाला एक पूरा पृष्ठ क्यों होगा।

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let


2

एक बहुत ही सामान्य समस्या जिसका वर्णन अभी तक नहीं किया गया है कि फ्रंट-एंड कोडर्स अक्सर चलते हैं वह स्कोप है जो HTML में इनलाइन ईवेंट हैंडलर में दिखाई देता है - उदाहरण के लिए,

<button onclick="foo()"></button>

किसी on*विशेषता को संदर्भित करने वाले चर का दायरा या तो होना चाहिए:

  • वैश्विक (इनलाइन काम करने वाले हैंडलर लगभग हमेशा वैश्विक चर का संदर्भ देते हैं)
  • दस्तावेज़ की एक संपत्ति (जैसे, querySelectorएक स्टैंडअलोन चर के रूप में इंगित करेगा document.querySelector; दुर्लभ)
  • तत्व की एक प्रॉपर्टी हैंडलर से जुड़ी होती है (जैसे ऊपर; दुर्लभ)

अन्यथा, जब हैंडलर का उपयोग किया जाता है, तो आपको एक रेफरेंस मिलेगा। इसलिए, उदाहरण के लिए, यदि इनलाइन हैंडलर एक फ़ंक्शन का संदर्भ देता है, जो कि अंदर परिभाषित हैwindow.onload या $(function() {, संदर्भ विफल हो जाएगा, क्योंकि इनलाइन हैंडलर वैश्विक दायरे में केवल संदर्भ चर हो सकता है, और फ़ंक्शन वैश्विक नहीं है:

के गुण documentऔर तत्व हैंडलर को भी इनलाइन संचालकों के अंदर स्टैंडअलोन चर के रूप में संदर्भित किया जा सकता है क्योंकि इनलाइन संचालकों लागू कर रहे हैं जुड़ा हुआ है के गुणों के अंदर दो के withब्लॉक , के लिए एक document, तत्व के लिए एक। इन हैंडलर के अंदर वेरिएबल्स की स्कोप चेन बेहद अचूक होती है , और एक वर्किंग इवेंट हैंडलर को संभवतः ग्लोबल होने के लिए एक फंक्शन की आवश्यकता होगी (और अनावश्यक ग्लोबल प्रदूषण से शायद बचा जाना चाहिए )।

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


एक अलग नोट पर, सामान्य <script>टैग के विपरीत , जो शीर्ष स्तर पर चलता है, ईएस 6 मॉड्यूल के अंदर कोड अपने निजी दायरे में चलता है। एक सामान्य <script>टैग के शीर्ष पर परिभाषित एक चर वैश्विक है, इसलिए आप इसे अन्य <script>टैग में संदर्भित कर सकते हैं , जैसे:

लेकिन ES6 मॉड्यूल का शीर्ष स्तर वैश्विक नहीं है । ES6 मॉड्यूल के शीर्ष पर घोषित एक चर केवल उस मॉड्यूल के अंदर दिखाई देगा, जब तक कि चर स्पष्ट रूप से exportएड नहीं होता है, या जब तक कि यह वैश्विक ऑब्जेक्ट की संपत्ति को नहीं सौंपा जाता है।

एक ES6 मॉड्यूल का शीर्ष स्तर सामान्य में शीर्ष स्तर पर एक IIFE के अंदर के समान है <script>। मॉड्यूल किसी भी चर का संदर्भ दे सकता है जो वैश्विक हैं, और मॉड्यूल के अंदर कुछ भी संदर्भित नहीं कर सकता है जब तक कि मॉड्यूल स्पष्ट रूप से इसके लिए डिज़ाइन नहीं किया गया हो।


1

जावास्क्रिप्ट में दो प्रकार के क्षेत्र होते हैं:

  • स्थानीय गुंजाइश
  • वैश्विक कार्यक्षेत्र

नीचे के फ़ंक्शन में एक स्थानीय स्कोप वैरिएबल है carName। और यह चर फ़ंक्शन के बाहर से पहुंच योग्य नहीं है।

function myFunction() {
    var carName = "Volvo";
    alert(carName);
    // code here can use carName
}

नीचे वर्ग में एक वैश्विक गुंजाइश चर है carName। और यह चर कक्षा में हर जगह से सुलभ है।

class {

    var carName = " Volvo";

    // code here can use carName

    function myFunction() {
        alert(carName);
        // code here can use carName 
    }
}

1

ES5 और पहले:

जावास्क्रिप्ट में चर शुरू में (पूर्व ES6) lexically समारोह scoped थे। शब्द lexically scoped का अर्थ है कि आप कोड पर 'देख' कर चर का दायरा देख सकते हैं।

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

  1. जब कोई फ़ंक्शन एक वैरिएबल वैल्यू को हल करने के लिए देखता है तो यह पहले अपने स्वयं के दायरे को देखता है। यह फ़ंक्शन बॉडी है, अर्थात घुंघराले कोष्ठक के बीच सब कुछ {} ( अन्य कार्यों के अंदर चर को छोड़कर जो इस दायरे में हैं)।
  2. यदि यह फ़ंक्शन बॉडी के अंदर वैरिएबल को नहीं ढूँढ सकता है तो यह चेन तक चढ़ जाएगा और फ़ंक्शन को उस फ़ंक्शन में वेरिएबल स्कोप को देखेगा जहां फ़ंक्शन परिभाषित किया गया था । यह वही है जो शाब्दिक दायरे के साथ है, हम उस कोड में देख सकते हैं जहां यह फ़ंक्शन परिभाषित किया गया था और इस प्रकार केवल कोड को देखकर गुंजाइश श्रृंखला निर्धारित कर सकता है।

उदाहरण:

// global scope
var foo = 'global';
var bar = 'global';
var foobar = 'global';

function outerFunc () {
 // outerFunc scope
 var foo = 'outerFunc';
 var foobar = 'outerFunc';
 innerFunc();
 
 function innerFunc(){
 // innerFunc scope
  var foo = 'innerFunc';
  console.log(foo);
  console.log(bar);
  console.log(foobar);
  }
}

outerFunc();

क्या जब हम चर लॉग इन करने की कोशिश कर रहे हैं होता है foo, barऔर foobarकंसोल के लिए निम्नलिखित है:

  1. हम फू को कंसोल में लॉग इन करने की कोशिश करते हैं, फ्यू को फंक्शन के अंदर पाया जा सकता innerFuncहै। इसलिए, फू का मूल्य स्ट्रिंग को हल किया जाता है innerFunc
  2. हम बार को कंसोल में लॉग इन करने की कोशिश करते हैं, बार को फंक्शन के अंदर नहीं पाया जा सकता innerFuncहै। इसलिए, हमें गुंजाइश श्रृंखला पर चढ़ने की आवश्यकता है । हम पहले उस बाहरी फ़ंक्शन को देखते हैं जिसमें फ़ंक्शन innerFuncपरिभाषित किया गया था। यह फंक्शन है outerFunc। इसके दायरे में outerFuncहम वैरिएबल बार पा सकते हैं, जो स्ट्रिंग 'आउटरफंक' रखती है।
  3. फोबार इनरफंक में नहीं पाया जा सकता है। । इसलिए, हमें गुंजाइश श्रृंखला को इनरफून गुंजाइश पर चढ़ने की आवश्यकता है । यह भी यहां नहीं पाया जा सकता है, हम वैश्विक स्तर पर एक और स्तर पर चढ़ते हैं (अर्थात सबसे बाहरी क्षेत्र)। हम यहां वैरिएबल फोब्बर पाते हैं जो स्ट्रिंग को 'ग्लोबल' रखता है। अगर जेएस इंजन रेफरेंस को फेंक देगा तो स्कोप चेन पर चढ़ने के बाद यह वैरिएबल नहीं पाएगा ।

ES6 (ईएस 2015) और पुराने:

Lexically गुंजाइश और scopechain की एक ही अवधारणा अभी भी में लागू होते हैं ES6। हालाँकि चर घोषित करने के एक नए तरीके की शुरुआत की गई थी। निम्नलिखित हैं:

  • let: ब्लॉक स्कॉप्ड वैरिएबल बनाता है
  • const: एक ब्लॉक स्कॉप्ड वैरिएबल बनाता है जिसे आरंभीकृत किया जाना है और पुन: असाइन नहीं किया जा सकता है

बीच varऔर let/ और सबसे बड़ा अंतर constयह है कि varफ़ंक्शन स्कॉप किया गया है जबकि let/ constब्लॉक स्कॉप्ड हैं। इसका उदाहरण देने के लिए यहां एक उदाहरण दिया गया है:

let letVar = 'global';
var varVar = 'global';

function foo () {
  
  if (true) {
    // this variable declared with let is scoped to the if block, block scoped
    let letVar = 5;
    // this variable declared with let is scoped to the function block, function scoped
    var varVar = 10;
  }
  
  console.log(letVar);
  console.log(varVar);
}


foo();

उपरोक्त उदाहरण में letVar मान को वैश्विक रूप से लॉग करता है क्योंकि घोषित किए गए चर letब्लॉक ब्लॉक किए गए हैं। वे अपने संबंधित ब्लॉक के बाहर मौजूद रहना बंद कर देते हैं, इसलिए यदि वेरिएबल को ब्लॉक से बाहर नहीं पहुँचा जा सकता है।


0

EcmaScript5 में मुख्य रूप से दो स्कोप, लोकल स्कोप और ग्लोबल स्कोप होते हैं लेकिन इम्मास्क्रिप्ट 6 में हमारे पास मुख्य रूप से तीन स्कोप, लोकल स्कोप, ग्लोबल स्कोप और एक नया स्कोप होता है जिसे ब्लॉक स्कोप कहा जाता है

ब्लॉक स्कोप का उदाहरण है: -

for ( let i = 0; i < 10; i++)
{
 statement1...
statement2...// inside this scope we can access the value of i, if we want to access the value of i outside for loop it will give undefined.
}

0

ECMAScript 6 ने लेट और कॉन्स्टेबल कीवर्ड पेश किए। इन कीवर्ड का उपयोग var कीवर्ड के स्थान पर किया जा सकता है। Var कीवर्ड के विपरीत, let और const कीवर्ड ब्लॉक स्टेटमेंट्स के अंदर स्थानीय दायरे की घोषणा का समर्थन करते हैं।

var x = 10
let y = 10
const z = 10
{
  x = 20
  let y = 20
  const z = 20
  {
    x = 30
    // x is in the global scope because of the 'var' keyword
    let y = 30
    // y is in the local scope because of the 'let' keyword
    const z = 30
    // z is in the local scope because of the 'const' keyword
    console.log(x) // 30
    console.log(y) // 30
    console.log(z) // 30
  }
  console.log(x) // 30
  console.log(y) // 20
  console.log(z) // 20
}

console.log(x) // 30
console.log(y) // 10
console.log(z) // 10

0

मुझे वास्तव में स्वीकृत उत्तर पसंद है लेकिन मैं इसे जोड़ना चाहता हूं:

स्कोप सभी घोषित पहचानकर्ताओं (चर) की एक लुक-अप सूची एकत्र करता है और रखता है, और नियमों का एक सख्त सेट लागू करता है कि ये वर्तमान में कोड निष्पादित करने के लिए कैसे सुलभ हैं।

स्कोप उनके पहचानकर्ता नाम से चर देखने के लिए नियमों का एक समूह है।

  • यदि एक चर को तत्काल दायरे में नहीं पाया जा सकता है, तो इंजन अगले बाहरी युक्त स्कोप को सुरक्षित करता है, जब तक नहीं मिलता है या तब तक जारी रहता है जब तक कि सबसे बाहरी (उर्फ, वैश्विक) स्कोप नहीं पहुंच जाता।
  • क्या नियमों का समूह निर्धारित करता है कि एक चर (पहचानकर्ता) को कहां और कैसे देखा जा सकता है। यह लुक-अप वैरिएबल को असाइन करने के उद्देश्यों के लिए हो सकता है, जो एक LHS (लेफ्ट-हैंड-साइड) संदर्भ है, या यह इसके मूल्य को पुनः प्राप्त करने के प्रयोजनों के लिए हो सकता है, जो कि RHS (राइट-साइड) संदर्भ है ।
  • एलएचएस संदर्भ असाइनमेंट ऑपरेशन के परिणामस्वरूप होता है। स्कोप-संबंधित असाइनमेंट फ़ंक्शन ऑपरेटर के लिए (ऑपरेटर को असाइन करें) पास करने के लिए = ऑपरेटर के साथ या तो हो सकता है।
  • जावास्क्रिप्ट इंजन निष्पादित होने से पहले पहले कोड को संकलित करता है, और ऐसा करने में, यह var a = 2 जैसे बयानों को विभाजित करता है; दो अलग-अलग चरणों में: 1। सबसे पहले, var को उस दायरे में घोषित करने के लिए। यह कोड निष्पादन से पहले, शुरुआत में किया जाता है। 2। बाद में, वेरिएबल (LHS संदर्भ) देखने के लिए a = 2 और पाए जाने पर इसे असाइन करें।
  • एलएचएस और आरएचएस संदर्भ लुक-अप दोनों ही वर्तमान में लागू होने वाले दायरे में शुरू होते हैं, और यदि आवश्यकता होती है (अर्थात, वे नहीं ढूंढते हैं कि वे वहां क्या देख रहे हैं), तो वे नेस्टेड गुंजाइश, एक गुंजाइश (मंजिल) पर काम करते हैं ) एक समय पर, पहचानकर्ता की तलाश में, जब तक वे वैश्विक (ऊपरी मंजिल) तक पहुंचते और रुकते नहीं हैं, और या तो इसे ढूंढते हैं, या नहीं। संदर्भ में अपूर्ण RHS संदर्भ परिणाम को फेंका जा रहा है। अधूरा एलएचएस संदर्भ एक स्वचालित, अंतर्निहित रूप से उस नाम के वैश्विक (यदि स्ट्रिक्ट मोड में नहीं है), या एक संदर्भError (यदि स्ट्रिक्ट मोड में) में परिणाम है।
  • स्कोप में "बुलबुले" की एक श्रृंखला होती है जो प्रत्येक कंटेनर या बाल्टी के रूप में कार्य करती है, जिसमें पहचानकर्ता (चर, फ़ंक्शन) घोषित किए जाते हैं। ये बुलबुले एक दूसरे के अंदर बड़े करीने से घोंसला बनाते हैं, और यह घोंसला लेखक के समय पर परिभाषित किया गया है।

-3

जावास्क्रिप्ट में दो प्रकार के स्कोप हैं।

  1. ग्लोबल स्कोप : वैरिएबल को ग्लोबल स्कोप में घोषित किया जाता है, प्रोग्राम में कहीं भी आसानी से इस्तेमाल किया जा सकता है। उदाहरण के लिए:

    var carName = " BMW";
    
    // code here can use carName
    
    function myFunction() {
         // code here can use carName 
    }
  2. फ़ंक्शनल स्कोप या लोकल स्कोप : इस स्कोप में घोषित किया गया वेरिएबल केवल अपने फंक्शन में इस्तेमाल किया जा सकता है। उदाहरण के लिए:

    // code here can not use carName
    function myFunction() {
       var carName = "BMW";
       // code here can use carName
    }
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.