"Let" और "var" का उपयोग करने में क्या अंतर है?


4537

ECMAScript 6 पेश किया गया let वक्तव्य किया

मैंने सुना है कि इसे "स्थानीय" चर के रूप में वर्णित किया गया है, लेकिन मुझे अभी भी यकीन नहीं है कि यह किस तरह से अलग व्यवहार करता है var कीवर्ड की ।

क्या अंतर हैं? कब letइस्तेमाल किया जाना चाहिए var?


104
ECMAScript मानक है और 6 वें संस्करण के मसौदेlet में शामिल है और अंतिम विनिर्देश में इसकी संभावना सबसे अधिक होगी।
रिचर्ड एयोटे

5
ES6 सुविधाओं (लेट सहित) के अप टू डेट समर्थन मैट्रिक्स के लिए kangax.github.io/es5-compat-table/es6 देखें । फ़ायरफ़ॉक्स, क्रोम और IE11 लिखने के समय सभी इसका समर्थन करते हैं (हालांकि मेरा मानना ​​है कि एफएफ का कार्यान्वयन काफी मानक नहीं है)।
निको बर्न्स

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

1
यह एक बहुत अच्छी रीडिंग है wesbos.com/javascript-scoping
onmyway133

1
अच्छी तरह से समझाया गया जवाब यहाँ stackoverflow.com/a/43994458/5043867
Pardeep Jain

जवाबों:


6094

स्कोपिंग नियम

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

function run() {
  var foo = "Foo";
  let bar = "Bar";

  console.log(foo, bar);

  {
    let baz = "Bazz";
    console.log(baz);
  }

  console.log(baz); // ReferenceError
}

run();

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

एक और स्टैकओवरफ़्लो प्रश्न से इस उदाहरण को देखें :

var funcs = [];
// let's create 3 functions
for (var i = 0; i < 3; i++) {
  // and store them in funcs
  funcs[i] = function() {
    // each should log its value.
    console.log("My value: " + i);
  };
}
for (var j = 0; j < 3; j++) {
  // and now let's run each one to see
  funcs[j]();
}

My value: 3 हर बार कंसोल के लिए आउटपुट था funcs[j](); गया था क्योंकि अनाम फ़ंक्शन उसी चर के लिए बाध्य थे।

लोगों को छोरों से सही मूल्य पर कब्जा करने के लिए तुरंत आह्वान किए गए कार्यों का निर्माण करना था, लेकिन यह भी बालों वाला था।

उत्थापन

जबकि varकीवर्ड के साथ घोषित किए गए वेरिएबल्स को फहराया जाता है ( undefinedकोड चलने से पहले के साथ आरंभ किया जाता है) जिसका अर्थ है कि वे घोषित किए जाने से पहले ही अपने संलग्नक दायरे में पहुंच सकते हैं:

function run() {
  console.log(foo); // undefined
  var foo = "Foo";
  console.log(foo); // Foo
}

run();

letजब तक उनकी परिभाषा का मूल्यांकन नहीं किया जाता है तब तक वैरिएबल को प्रारंभ नहीं किया जाता है। आरंभीकरण से पहले उन तक पहुँचने से एक परिणाम होता है ReferenceError। वैरिएबल ने कहा कि ब्लॉक के शुरू से "टेम्पोरल डेड ज़ोन" में तब तक होना चाहिए जब तक कि इनिशियलाइज़ेशन प्रोसेस न हो जाए।

function checkHoisting() {
  console.log(foo); // ReferenceError
  let foo = "Foo";
  console.log(foo); // Foo
}

checkHoisting();

वैश्विक वस्तु संपत्ति बनाना

इसके letविपरीत var, शीर्ष स्तर पर, वैश्विक वस्तु पर कोई संपत्ति नहीं बनाता है:

var foo = "Foo";  // globally scoped
let bar = "Bar"; // globally scoped

console.log(window.foo); // Foo
console.log(window.bar); // undefined

पुन: घोषणा

सख्त मोड में, varआपको letसिंटैक्सएयर्रम उठाते समय उसी चर को उसी दायरे में फिर से घोषित करने देगा ।

'use strict';
var foo = "foo1";
var foo = "foo2"; // No problem, 'foo' is replaced.

let bar = "bar1";
let bar = "bar2"; // SyntaxError: Identifier 'bar' has already been declared

22
याद रखें आप जब चाहें ब्लॉक बना सकते हैं। function () {कोड; {let inBlock = 5; } कोड; };
औसत जो

177
तो क्या किसी ख़ास ब्लॉक में ज़रूरत न होने पर केवल स्मृति को मुक्त करने के लिए वक्तव्य देना उद्देश्य है?
NoBugs

219
@ नोबोग्स, हां, और यह प्रोत्साहित किया जाता है कि चर केवल उसी स्थान पर मौजूद हैं जहां उनकी आवश्यकता है।
बैटमैन

67
letब्लॉक अभिव्यक्ति let (variable declaration) statementगैर-मानक है और इसे भविष्य में हटा दिया जाएगा, Bugzilla.mozilla.org/show_bug.cgi?id=1023609
गजस

19
इसलिए, मैं अभी किसी भी मामले के बारे में नहीं सोच सकता जहाँ var का उपयोग करना किसी काम का हो। क्या कोई मुझे ऐसी स्थिति का उदाहरण दे सकता है, जहाँ var का उपयोग करना बेहतर हो?
लुइस सीइरा

621

letबंद के साथ समस्याओं से बचने के लिए भी इस्तेमाल किया जा सकता है। यह एक पुराने संदर्भ को रखने के बजाय ताजा मूल्य बांधता है जैसा कि नीचे दिए गए उदाहरणों में दिखाया गया है।

for(var i=1; i<6; i++) {
  $("#div" + i).click(function () { console.log(i); });
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<p>Clicking on each number will log to console:</p> 
<div id="div1">1</div>
<div id="div2">2</div>
<div id="div3">3</div>
<div id="div4">4</div>
<div id="div5">5</div>

ऊपर कोड एक क्लासिक जावास्क्रिप्ट क्लोजर समस्या दर्शाता है। iचर का संदर्भ वास्तविक मूल्य के बजाय क्लिक हैंडलर क्लोजर में संग्रहीत किया जा रहा है i

हर एक क्लिक हैंडलर एक ही ऑब्जेक्ट को संदर्भित करेगा क्योंकि केवल एक काउंटर ऑब्जेक्ट है जो 6 रखता है ताकि आपको प्रत्येक क्लिक पर छह मिलें।

सामान्य वर्कअराउंड इसे एक अनाम फ़ंक्शन में लपेटना और iएक तर्क के रूप में पास करना है। इस तरह के मुद्दों को भी उपयोग करके अब बचा जा सकता है letबजाय varके रूप में नीचे दिए गए कोड में दिखाया गया है।

(क्रोम और फ़ायरफ़ॉक्स 50 में परीक्षण किया गया)

for(let i=1; i<6; i++) {
  $("#div" + i).click(function () { console.log(i); });
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<p>Clicking on each number will log to console:</p> 
<div id="div1">1</div>
<div id="div2">2</div>
<div id="div3">3</div>
<div id="div4">4</div>
<div id="div5">5</div>


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

9
IE 11 समर्थन करता है let, लेकिन यह सभी बटन के लिए "6" अलर्ट करता है । क्या आपके पास यह कहने का कोई स्रोत letहै कि व्यवहार कैसे किया जाता है?
जिम हंज़िकर

10
लगता है कि आपका उत्तर सही व्यवहार है: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
जिम हंज़िकर

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

19
"लेट" का उपयोग इस समस्या को कम करता है। इसलिए प्रत्येक पुनरावृत्ति एक निजी स्वतंत्र ब्लॉक स्कोप बनाता है, लेकिन "i" वैरिएबल ब्लॉक के बाद के परिवर्तनों से अभी भी दूषित हो सकता है, (दी गई इटरेटर चर आमतौर पर ब्लॉक के भीतर नहीं बदला जाता है, लेकिन ब्लॉक के भीतर अन्य घोषित लेट वेरिएबल अच्छी तरह से हो सकते हैं) हो) और ब्लॉक के भीतर घोषित किए गए किसी भी फ़ंक्शन को ब्लॉक किए जाने पर घोषित किए गए अन्य कार्यों के लिए "i" के मान को भ्रष्ट कर सकता है क्योंकि वे एक ही निजी ब्लॉक गुंजाइश को साझा करते हैं इसलिए "i" के समान संदर्भ।
गैरी

198

बीच क्या अंतर है letऔर var?

  • एक varकथन का उपयोग करके परिभाषित एक चर पूरे फ़ंक्शन में जाना जाता है जिसे फ़ंक्शन की शुरुआत से परिभाषित किया गया है। (*)
  • एक letकथन का उपयोग करके परिभाषित एक चर केवल उस खंड में जाना जाता है जिसे वह उस समय से परिभाषित किया गया है, जिस समय से इसे आगे परिभाषित किया गया है। (**)

अंतर को समझने के लिए, निम्नलिखित कोड पर विचार करें:

// 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पूरे समारोह में जाना जाता है।

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


क्या letआज इसका उपयोग करना सुरक्षित है?

कुछ लोग यह तर्क देंगे कि भविष्य में हम केवल स्टेटमेंट्स का उपयोग करेंगे और वह वेरिएंट अप्रचलित हो जाएगा। जावास्क्रिप्ट गुरु काइल सिम्पसन ने एक बहुत विस्तृत लेख लिखा कि वह क्यों मानता है कि ऐसा नहीं होगा

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

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

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

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

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

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

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


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

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


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

(**) ब्लॉक स्कोप किए गए चर नहीं फहराए जाते हैं


14
उत्तर v4 के बारे में: iफ़ंक्शन-ब्लॉक में हर जगह जाना जाता है! यह undefinedतब तक शुरू होता है जब तक आप फहराने के कारण नहीं होते। पीएस: letभी फहराया जाता है (इसके शीर्ष पर ब्लॉक होता है), लेकिन ReferenceErrorपहले असाइनमेंट से पहले ब्लॉक में संदर्भित होने पर। (ps2: मैं एक प्रो-सेमीकोलन थोड़े आदमी हूं लेकिन आपको वास्तव में ब्लॉक के बाद अर्धविराम की जरूरत नहीं है)। कहा जा रहा है, समर्थन के संबंध में वास्तविकता-जांच को जोड़ने के लिए धन्यवाद!
गीतालीलाब

@ गीतालारब: मोज़िला डेवलपर नेटवर्क के अनुसार : " ईसीएमएस्क्रिप्ट 2015 में, बाइंडिंग वैरिएबल होस्टिंग के अधीन नहीं हैं, जिसका अर्थ है कि घोषणाएं वर्तमान निष्पादन संदर्भ के शीर्ष पर नहीं जाती हैं।" - वैसे भी, मैंने अपने उत्तर में कुछ सुधार किए हैं जो कि बीच में फहराए जाने वाले व्यवहार के अंतर को स्पष्ट करना चाहिए letऔर var!
जॉन सलेगर्स

1
आपके उत्तर में बहुत सुधार हुआ (मैंने पूरी जाँच की)। ध्यान दें कि आपने अपनी टिप्पणी में जिस लिंक को संदर्भित किया है, वह यह भी कहता है: "(चलो) वेरिएबल ब्लॉक के प्रारंभ से" अस्थायी डेड ज़ोन "में है, जब तक कि इनिशियलाइज़ेशन प्रक्रिया नहीं हो जाती।" इसका अर्थ है कि 'पहचानकर्ता' (पाठ-स्ट्रिंग '' कुछ को इंगित करने के लिए ' आरक्षित ) पहले से ही संबंधित दायरे में आरक्षित है, अन्यथा यह रूट / होस्ट / विंडो स्कोप का हिस्सा बन जाएगा। मेरे लिए व्यक्तिगत रूप से, 'ध्वजारोहण' का अर्थ है '' पहचानकर्ता '' को उनके प्रासंगिक दायरे से जोड़ने / जोड़ने के अलावा और कुछ नहीं; उनके आरंभीकरण / असाइनमेंट / संशोधन को छोड़कर!
गीतरलैब

और .. + 1। वह काइल सिम्पसन लेख जो आपने जोड़ा है वह एक उत्कृष्ट रीड है, इसके लिए धन्यवाद! यह "टेम्पोरल डेड ज़ोन" उर्फ ​​"टीडीजेड" के बारे में भी स्पष्ट है। एक दिलचस्प बात यह है कि मैं जोड़ना चाहते हैं: मैं MDN पर पढ़ा है कि letऔर constकर रहे थे केवल उपयोग करने के लिए सिफारिश जब आप वास्तव में उनके अतिरिक्त कार्यक्षमता की जरूरत है , को लागू करने / जाँच इन अतिरिक्त सुविधाओं (जैसे लिखने केवल स्थिरांक) 'अधिक काम में परिणाम है क्योंकि (वर्तमान) इंजन (लागू) / चेक / सत्यापन / सेटअप के लिए (स्कोप-ट्री में अतिरिक्त स्कोप-नोड्स)।
गीतांबर

1
ध्यान दें कि MDN कहता है कि IE व्याख्या सही ढंग से करता है। यह किसका है? developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
कटिंका हेसेलिंक

146

यहां कुछ उदाहरणों के साथ कीवर्ड का स्पष्टीकरण दिया गया हैlet

letबहुत पसंद है var। मुख्य अंतर यह है कि एक varचर का दायरा संपूर्ण संलग्नक कार्य है

विकिपीडिया पर यह तालिका बताती है कि कौन से ब्राउज़र जावास्क्रिप्ट 1.7 का समर्थन करते हैं।

ध्यान दें कि केवल मोज़िला और क्रोम ब्राउज़र इसका समर्थन करते हैं। IE, सफारी, और संभावित रूप से अन्य नहीं।


5
लिंक किए गए दस्तावेज़ से पाठ का मुख्य हिस्सा लगता है, "चलो var की तरह बहुत काम करते हैं। मुख्य अंतर यह है कि एक चर चर का दायरा संपूर्ण संलग्नक फ़ंक्शन है"।
माइकल बूर

50
जबकि यह तकनीकी रूप से कहने के लिए सही है कि IE इसका समर्थन नहीं करता है, यह कहना अधिक सही है कि यह केवल एक मोज़िला एक्सटेंशन है।
olliej

55
@olliej, वास्तव में मोज़िला खेल से आगे है। का पेज 19 देखें ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf
टायलर क्रॉम्पटन

@ टायलर क्रॉम्पटन केवल उन शब्दों का समूह है जो वर्षों से आरक्षित हैं। जब मोज़िला जोड़ा गया तो यह विशुद्ध रूप से मोज़िला विस्तार था, जिसमें कोई संबंधित कल्पना नहीं थी। ES6 को लेट स्टेटमेंट्स के लिए व्यवहार को परिभाषित करना चाहिए, लेकिन बाद में मोज़िला ने वाक्य रचना पेश किया। याद रखें कि moz में E4X भी है, जो पूरी तरह से मृत है और केवल moz है।
olliej


112

स्वीकृत उत्तर एक बिंदु याद आ रहा है:

{
  let a = 123;
};

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

19
स्वीकृत उत्तर इस बिंदु को इसके उदाहरण में स्पष्ट नहीं करता है। स्वीकृत उत्तर ने केवल forलूप इनिशियलाइज़र में इसका प्रदर्शन किया, नाटकीय रूप से की सीमाओं के आवेदन के दायरे को कम कर दिया let। Upvoted।
जॉन डेविस

37
@ stimpy77 यह स्पष्ट रूप से बताता है "चलो पास के घेरने वाले ब्लॉक में स्कूप किया गया है"; क्या हर तरीके को प्रकट करने की आवश्यकता है?
डेव न्यूटन

6
बहुत सारे उदाहरण थे और उनमें से किसी ने भी इस मामले को सही ढंग से प्रदर्शित नहीं किया .. मैंने स्वीकार किए गए उत्तर और इस एक दोनों को उखाड़ फेंका होगा?
जॉन डेविस

5
यह योगदान दर्शाता है कि "ब्लॉक" बस कोष्ठक में संलग्न लाइनों का एक सेट हो सकता है; अर्थात इसे किसी भी प्रकार के नियंत्रण प्रवाह, पाश आदि से संबद्ध होने की आवश्यकता नहीं है
वेबेलो

81

let

ब्लॉक स्कोप

letकीवर्ड का उपयोग करते हुए घोषित चर ब्लॉक-स्कोप किए गए हैं, जिसका अर्थ है कि वे केवल ब्लॉक में उपलब्ध हैं में जिसमें वे घोषित किए गए थे।

शीर्ष स्तर पर (एक समारोह के बाहर)

शीर्ष स्तर पर, वैरिएबल घोषित किए गए वैरिएबल letवैश्विक ऑब्जेक्ट पर गुण नहीं बनाते हैं।

var globalVariable = 42;
let blockScopedVariable = 43;

console.log(globalVariable); // 42
console.log(blockScopedVariable); // 43

console.log(this.globalVariable); // 42
console.log(this.blockScopedVariable); // undefined

एक समारोह के अंदर

एक फ़ंक्शन के अंदर (लेकिन एक ब्लॉक के बाहर), के रूप letमें एक ही गुंजाइश है var

(() => {
  var functionScopedVariable = 42;
  let blockScopedVariable = 43;

  console.log(functionScopedVariable); // 42
  console.log(blockScopedVariable); // 43
})();

console.log(functionScopedVariable); // ReferenceError: functionScopedVariable is not defined
console.log(blockScopedVariable); // ReferenceError: blockScopedVariable is not defined

एक ब्लॉक के अंदर

letकिसी ब्लॉक के अंदर उपयोग किए जा रहे चर को उस ब्लॉक के बाहर एक्सेस नहीं किया जा सकता है।

{
  var globalVariable = 42;
  let blockScopedVariable = 43;
  console.log(globalVariable); // 42
  console.log(blockScopedVariable); // 43
}

console.log(globalVariable); // 42
console.log(blockScopedVariable); // ReferenceError: blockScopedVariable is not defined

एक लूप के अंदर

letलूप में घोषित चर केवल उस लूप के अंदर संदर्भित किए जा सकते हैं।

for (var i = 0; i < 3; i++) {
  var j = i * 2;
}
console.log(i); // 3
console.log(j); // 4

for (let k = 0; k < 3; k++) {
  let l = k * 2;
}
console.log(typeof k); // undefined
console.log(typeof l); // undefined
// Trying to do console.log(k) or console.log(l) here would throw a ReferenceError.

बंद के साथ लूप्स

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

// Logs 3 thrice, not what we meant.
for (var i = 0; i < 3; i++) {
  setTimeout(() => console.log(i), 0);
}

// Logs 0, 1 and 2, as expected.
for (let j = 0; j < 3; j++) {
  setTimeout(() => console.log(j), 0);
}

टेम्पोरल डेड जोन

टेम्परेरी डेड ज़ोन की वजह से , घोषित किए गए वेरिएबल को घोषित किए letजाने से पहले एक्सेस नहीं किया जा सकता है। ऐसा करने का प्रयास एक त्रुटि फेंकता है।

console.log(noTDZ); // undefined
var noTDZ = 43;
console.log(hasTDZ); // ReferenceError: hasTDZ is not defined
let hasTDZ = 42;

फिर से घोषित नहीं

आप एक ही चर को कई बार प्रयोग करके घोषित नहीं कर सकते let। आप letउसी पहचानकर्ता के साथ एक चर का उपयोग करने की घोषणा नहीं कर सकते हैं जैसा कि एक अन्य चर का उपयोग करके घोषित किया गया था var

var a;
var a; // Works fine.

let b;
let b; // SyntaxError: Identifier 'b' has already been declared

var c;
let c; // SyntaxError: Identifier 'c' has already been declared

const

const के समान है let ब्लॉक-स्कोप के और इसमें TDZ है। हालांकि, दो चीजें हैं जो अलग-अलग हैं।

फिर से असाइन नहीं किया गया

परिवर्तनीय घोषित का उपयोग constफिर से नहीं किया जा सकता है।

const a = 42;
a = 43; // TypeError: Assignment to constant variable.

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

const obj = {};
obj.a = 42;
console.log(obj.a); // 42

यदि आप एक अपरिवर्तनीय वस्तु रखना चाहते हैं, तो आपको उपयोग करना चाहिए Object.freeze()

प्रारंभिक आवश्यक है

चर का उपयोग करते समय आपको हमेशा एक मूल्य निर्दिष्ट करना चाहिए const

const a; // SyntaxError: Missing initializer in const declaration

51

यहाँ दोनों के बीच अंतर के लिए एक उदाहरण है (क्रोम के लिए शुरू किया गया समर्थन):
यहां छवि विवरण दर्ज करें

जैसा कि आप देख सकते हैं कि var jचर अभी भी लूप स्कोप (ब्लॉक स्कोप) के बाहर एक मूल्य है, लेकिन let iलूप स्कोप के बाहर वैरिएबल अपरिभाषित है।

"use strict";
console.log("var:");
for (var j = 0; j < 2; j++) {
  console.log(j);
}

console.log(j);

console.log("let:");
for (let i = 0; i < 2; i++) {
  console.log(i);
}

console.log(i);


2
मैं यहाँ क्या उपकरण देख रहा हूँ?
बार्टन

20
क्रोम देवतुल
vlio20

दालचीनी के लिए डेस्कटॉप एप्लेट के एक डेवलपर के रूप में, मैं इस तरह के चमकदार टूल के संपर्क में नहीं आया हूं।
बार्टन

48

कुछ सूक्ष्म अंतर हैं - letस्कोपिंग अधिक व्यवहार करता है जैसे कि वैरिएबल स्कोपिंग किसी अन्य भाषा में कम या ज्यादा करता है।

उदा। यह घेरने वाले ब्लॉक को स्कोप करता है, वे घोषित होने से पहले मौजूद नहीं हैं, आदि।

हालांकि यह ध्यान देने योग्य है कि letयह केवल नए जावास्क्रिप्ट कार्यान्वयन का एक हिस्सा है और इसमें ब्राउज़र समर्थन की अलग-अलग डिग्री है


11
यह भी ध्यान देने योग्य है कि ECMAScript मानक है और 6 वें संस्करण के मसौदेlet में शामिल है और अंतिम विनिर्देश में सबसे अधिक संभावना होगी।
रिचर्ड अयोटे

23
यही अंतर 3 साल बनाता है: D
olliej

4
बस इस सवाल पर अड़ गए और 2012 में यह अभी भी मामला है कि केवल मोज़िला ब्राउज़र समर्थन करते हैं let। सफारी, IE, और चोम सभी नहीं है।
छद्मवसंत

2
गलती से दुर्घटना पर आंशिक ब्लॉक गुंजाइश बनाने का विचार एक अच्छा बिंदु है, सावधान रहें, letलहरा नहीं करता है, letअपने ब्लॉक के शीर्ष पर एक परिभाषित द्वारा परिभाषित चर का उपयोग करने के लिए । यदि आपके पास एक ifकथन है जो कोड की कुछ पंक्तियों से अधिक है, तो आप भूल सकते हैं कि आप उस चर का उपयोग तब तक नहीं कर सकते हैं जब तक कि इसे परिभाषित नहीं किया जाता है। महान बिंदु !!!
एरिक बिशर्ड

2
@EricB: हां और ना: "में ECMAScript 2015, let फहराने जाएगा चर ब्लॉक के शीर्ष करने हालांकि, एक में चर घोषणा परिणामों से पहले ब्लॉक में चर संदर्भित। ReferenceError (मेरी टिप्पणी: अच्छे पुराने के बजाय undefined)। The जब तक घोषणा नहीं हो जाती तब तक ब्लॉक की शुरुआत से एक 'अस्थायी मृत क्षेत्र' में परिवर्तनशील है। " समान "स्विच स्टेटमेंट्स के लिए जाता है क्योंकि केवल एक अंतर्निहित ब्लॉक है"। स्रोत: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
GitaarLAB

26

मुख्य अंतर स्कोप का अंतर है, जबकि इसे केवल घोषित स्कोप के अंदर ही उपलब्ध किया जा सकता है , जैसे कि लूप के लिए, उदाहरण के लिए, लूप के बाहर var को एक्सेस किया जा सकता है। MDN में प्रलेखन से (उदाहरण MDN से भी):

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

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

function varTest() {
  var x = 1;
  if (true) {
    var x = 2;  // same variable!
    console.log(x);  // 2
  }
  console.log(x);  // 2
}

function letTest() {
  let x = 1;
  if (true) {
    let x = 2;  // different variable
    console.log(x);  // 2
  }
  console.log(x);  // 1
}`

कार्यक्रमों और कार्यों के शीर्ष स्तर पर, जाने के विपरीत, वर , वैश्विक वस्तु पर एक संपत्ति का निर्माण नहीं करता। उदाहरण के लिए:

var x = 'global';
let y = 'global';
console.log(this.x); // "global"
console.log(this.y); // undefined

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

var a = 1;
var b = 2;

if (a === 1) {
  var a = 11; // the scope is global
  let b = 22; // the scope is inside the if-block

  console.log(a);  // 11
  console.log(b);  // 22
} 

console.log(a); // 11
console.log(b); // 2

यह भी मत भूलना कि यह ECMA6 सुविधा है, इसलिए इसे अभी तक पूरी तरह से समर्थित नहीं किया गया है, इसलिए यह हमेशा बेहतर है कि यह ECMA5 को बैबल आदि का उपयोग करके ... अधिक जानकारी के लिए babel वेबसाइट देखें।


24
  • परिवर्तनीय नहीं उत्थापन

    letहोगा नहीं उत्तोलक ब्लॉक वे में प्रदर्शित की पूरी गुंजाइश है। इसके विपरीत, varनीचे के रूप में फहराने सकता है।

    {
       console.log(cc); // undefined. Caused by hoisting
       var cc = 23;
    }
    
    {
       console.log(bb); // ReferenceError: bb is not defined
       let bb = 23;
    }

    दरअसल, Per @Bergi, दोनों varऔर letफहराए जाते हैं

  • कचरा इकठा करना

    letमेमोरी को पुनः प्राप्त करने के लिए क्लोज़र और कचरा संग्रह से संबंधित ब्लॉक स्कोप उपयोगी है। विचार करें,

    function process(data) {
        //...
    }
    
    var hugeData = { .. };
    
    process(hugeData);
    
    var btn = document.getElementById("mybutton");
    btn.addEventListener( "click", function click(evt){
        //....
    });

    clickहैंडलर कॉलबैक की जरूरत नहीं है hugeDataसब पर चर। सैद्धांतिक रूप से, process(..)रन के बाद , विशाल डेटा संरचना hugeDataकचरा एकत्र किया जा सकता है। हालांकि, यह संभव है कि कुछ जेएस इंजन को अभी भी इस विशाल संरचना को रखना होगा, क्योंकि clickफ़ंक्शन के पूरे दायरे में बंद होने की संभावना है।

    हालांकि, ब्लॉक स्कोप एकत्रित किए गए कचरे को इस विशाल डेटा संरचना को बना सकता है।

    function process(data) {
        //...
    }
    
    { // anything declared inside this block can be garbage collected
        let hugeData = { .. };
        process(hugeData);
    }
    
    var btn = document.getElementById("mybutton");
    btn.addEventListener( "click", function click(evt){
        //....
    });
  • let छोरों

    letलूप में लूप के प्रत्येक पुनरावृत्ति के लिए इसे फिर से बाँध सकता है, जिससे यह सुनिश्चित हो सकता है कि पिछले लूप चलना के अंत से इसे फिर से असाइन किया जाए। विचार करें,

    // print '5' 5 times
    for (var i = 0; i < 5; ++i) {
        setTimeout(function () {
            console.log(i);
        }, 1000);  
    }

    हालाँकि, के varसाथ बदलेंlet

    // print 1, 2, 3, 4, 5. now
    for (let i = 0; i < 5; ++i) {
        setTimeout(function () {
            console.log(i);
        }, 1000);  
    }

    क्योंकि letएक के लिए उन नामों के साथ एक नया शाब्दिक वातावरण तैयार करें (एक प्रारंभिक अभिव्यक्ति b) प्रत्येक पुनरावृत्ति (पूर्ववर्ती अभिव्यक्ति का मूल्यांकन करने के लिए), अधिक विवरण यहाँ हैं


4
हां, वे फहराए जाते हैं, लेकिन ऐसा व्यवहार करते हैं मानो (ड्रम रोल) की वजह से फहराया नहीं गया है - टेम्पोरल डेड जोन - एक पहचानकर्ता के लिए एक बहुत ही नाटकीय नाम जब तक सुलभ नहीं है, तब तक :-)
ड्रेनई

तो चलो फहराया जाता है, लेकिन अनुपलब्ध है? वह is फहराया नहीं ’से अलग कैसे है?
एन

उम्मीद है कि ब्रायन या बर्गी इसका जवाब देने के लिए वापस आएंगे। क्या घोषणा को छोड़ दिया गया है, लेकिन असाइनमेंट नहीं है? धन्यवाद!
एन

1
@ एन-एट, यहाँ बर्गी का एक पद है, शायद आप इसमें उत्तर पा सकते हैं।
ज़ंगव

यह दिलचस्प है कि इसे उत्थापन भी कहा जाता है जब यह जाने देता है। मुझे लगता है कि तकनीकी रूप से पार्सिंग इंजन इसे पूर्व-कैप्चर कर रहा है, लेकिन सभी इरादों और उद्देश्यों के लिए एक प्रोग्रामर को इसका इलाज करना चाहिए जैसे कि यह मौजूद नहीं है। दूसरी ओर var के उत्थापन के एक प्रोग्रामर के निहितार्थ हैं।
N-

19

यहाँ एक उदाहरण है कि दूसरे ने जो पहले से लिखा है, उसे जोड़ दें। मान लीजिए कि आप फ़ंक्शन का एक सरणी बनाना चाहते हैं adderFunctions, जहां प्रत्येक फ़ंक्शन एकल नंबर तर्क लेता है और सरणी में फ़ंक्शन का तर्क और फ़ंक्शन का सूचकांक लौटाता है। कीवर्ड adderFunctionsका उपयोग करके एक लूप के साथ उत्पन्न करने की कोशिश करना varउस तरह से काम नहीं करेगा जिस तरह से कोई व्यक्ति भोलेपन से उम्मीद कर सकता है:

// An array of adder functions.
var adderFunctions = [];

for (var i = 0; i < 1000; i++) {
  // We want the function at index i to add the index to its argument.
  adderFunctions[i] = function(x) {
    // What is i bound to here?
    return x + i;
  };
}

var add12 = adderFunctions[12];

// Uh oh. The function is bound to i in the outer scope, which is currently 1000.
console.log(add12(8) === 20); // => false
console.log(add12(8) === 1008); // => true
console.log(i); // => 1000

// It gets worse.
i = -8;
console.log(add12(8) === 0); // => true

उपरोक्त प्रक्रिया कार्यों के वांछित सरणी को उत्पन्न नहीं करती है क्योंकि इसका iदायरा उस forखंड के पुनरावृत्ति से आगे निकलता है जिसमें प्रत्येक फ़ंक्शन बनाया गया था। इसके बजाय, लूप के अंत में, iप्रत्येक फ़ंक्शन के क्लोजर में प्रत्येक iअनाम फ़ंक्शन के लिए लूप के अंत में मूल्य (1000) को संदर्भित करता है adderFunctions। यह वह नहीं है जो हम चाहते थे: अब हमारे पास एक ही व्यवहार के साथ स्मृति में 1000 विभिन्न कार्यों की एक सरणी है। और यदि हम बाद में मूल्य को अद्यतन करते हैं i, तो उत्परिवर्तन सभी को प्रभावित करेगाadderFunctions

हालाँकि, हम letकीवर्ड का उपयोग करके फिर से कोशिश कर सकते हैं :

// Let's try this again.
// NOTE: We're using another ES6 keyword, const, for values that won't
// be reassigned. const and let have similar scoping behavior.
const adderFunctions = [];

for (let i = 0; i < 1000; i++) {
  // NOTE: We're using the newer arrow function syntax this time, but 
  // using the "function(x) { ..." syntax from the previous example 
  // here would not change the behavior shown.
  adderFunctions[i] = x => x + i;
}

const add12 = adderFunctions[12];

// Yay! The behavior is as expected. 
console.log(add12(8) === 20); // => true

// i's scope doesn't extend outside the for loop.
console.log(i); // => ReferenceError: i is not defined

इस बार, लूप के iप्रत्येक पुनरावृत्ति पर पलटाव है for। प्रत्येक फ़ंक्शन अब iफ़ंक्शन के निर्माण के समय का मान रखता है , और adderFunctionsअपेक्षा के अनुसार व्यवहार करता है।

अब, दो व्यवहारों को मिलाने वाली छवि और आप शायद देखेंगे कि नए letऔर constपुराने varको एक ही स्क्रिप्ट में मिलाने की सिफारिश क्यों नहीं की गई है। ऐसा करने से परिणाम कुछ शानदार भ्रमित कोड हो सकते हैं।

const doubleAdderFunctions = [];

for (var i = 0; i < 1000; i++) {
    const j = i;
    doubleAdderFunctions[i] = x => x + i + j;
}

const add18 = doubleAdderFunctions[9];
const add24 = doubleAdderFunctions[12];

// It's not fun debugging situations like this, especially when the
// code is more complex than in this example.
console.log(add18(24) === 42); // => false
console.log(add24(18) === 42); // => false
console.log(add18(24) === add24(18)); // => false
console.log(add18(24) === 2018); // => false
console.log(add24(18) === 2018); // => false
console.log(add18(24) === 1033); // => true
console.log(add24(18) === 1030); // => true

ऐसा आपके साथ नहीं होने दें। लिंटर का इस्तेमाल करें।

नोट: यह एक शिक्षण उदाहरण है जिसका उद्देश्य लूप में var/ letव्यवहार को प्रदर्शित करना है और फ़ंक्शन क्लोजर के साथ जिसे समझना भी आसान होगा। यह संख्या जोड़ने का एक भयानक तरीका होगा। लेकिन अनाम फ़ंक्शन क्लोजर में डेटा कैप्चर करने की सामान्य तकनीक का वास्तविक दुनिया में अन्य संदर्भों में सामना किया जा सकता है। YMMV।


2
@aborz: दूसरे उदाहरण में भी बहुत ही शांत अनाम फ़ंक्शन सिंटैक्स। यह वही है जो मैं C # में उपयोग कर रहा हूं। मैंने आज कुछ सीखा है।
बार्टन

सुधार: तकनीकी रूप से, एरो फ़ंक्शन सिंटैक्स का वर्णन यहाँ किया गया है => developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
बार्टन

3
वास्तव में, आप की जरूरत नहीं है let value = i;forबयान एक शाब्दिक ब्लॉक बनाता है।
टूथब्रश

17

अंतर प्रत्येक के साथ घोषित चर के दायरे में है।

व्यवहार में, अंतर के अंतर के कई उपयोगी परिणाम हैं:

  1. letचर केवल उनके निकटतम संलग्न ब्लॉक ( { ... }) में दिखाई देते हैं ।
  2. letचर केवल कोड की पंक्तियों में उपयोग करने योग्य होते हैं जो चर घोषित होने के बाद होते हैं (भले ही वे फहराए गए हों !)।
  3. letचर एक बाद varया द्वारा redeclared नहीं किया जा सकता है let
  4. वैश्विक letचर वैश्विक windowऑब्जेक्ट में नहीं जोड़े जाते हैं ।
  5. letचर को क्लोजर के साथ उपयोग करना आसान है (वे दौड़ की स्थिति पैदा नहीं करते हैं )।

letचरों की दृश्यता को कम करने और अप्रत्याशित नाम टकराने की संभावना को बढ़ाने के लिए लगाए गए प्रतिबंध जल्दी मिल जाएंगे। इससे चर को ट्रैक करना आसान हो जाता है और चर के बारे में पता चलता है, जिसमें उनकी रीचबिलिटी (अप्रयुक्त मेमोरी को पुनः प्राप्त करने में मदद करना) शामिल है।

इसके फलस्वरूप, let बड़े कार्यक्रमों में उपयोग किए जाने पर या जब स्वतंत्र रूप से विकसित रूपरेखाओं को नए और अनपेक्षित तरीकों से संयोजित किया जाता है चर की समस्याएं कम होती हैं।

varयदि आप सुनिश्चित हैं कि आप लूप (# 5) में क्लोजर का उपयोग करते समय या अपने कोड (# 4) में बाह्य-दृश्यमान वैश्विक चर घोषित करने के लिए एकल-बाध्यकारी प्रभाव चाहते हैं, तब भी उपयोगी हो सकते हैं। varयदि exportट्रांसपाइलर स्पेस से बाहर निकलता है और कोर लैंग्वेज में एक्सपोर्ट्स के लिए इस्तेमाल किया जा सकता है ।

उदाहरण

1. पास के एनक्लोजर ब्लॉक के बाहर कोई उपयोग नहीं: कोड का यह ब्लॉक एक संदर्भ त्रुटि को फेंक देगा, क्योंकि ब्लॉक का दूसरा उपयोग xउस ब्लॉक के बाहर होता है जहां यह घोषित किया गया है let:

{
    let x = 1;
}
console.log(`x is ${x}`);  // ReferenceError during parsing: "x is not defined".

इसके विपरीत, varकाम के साथ एक ही उदाहरण है ।

2. घोषणा से पहले कोई उपयोग नहीं:
कोड को ReferenceErrorचलाने से पहले कोड के इस ब्लॉक को फेंक दिया जाएगा क्योंकि xयह घोषित होने से पहले उपयोग किया जाता है:

{
    x = x + 1;  // ReferenceError during parsing: "x is not defined".
    let x;
    console.log(`x is ${x}`);  // Never runs.
}

इसके विपरीत, varपर्स के साथ एक ही उदाहरण और बिना किसी अपवाद को फेंकने के बिना चलता है।

3. कोई पुनर्वितरण नहीं: निम्नलिखित कोड दर्शाता है कि एक चर के साथ घोषित किया गया letहो सकता है बाद में पुन: घोषित नहीं किया जा सकता है:

let x = 1;
let x = 2;  // SyntaxError: Identifier 'x' has already been declared

4. ग्लोबल्स संलग्न नहीं हैं window:

var button = "I cause accidents because my name is too common.";
let link = "Though my name is common, I am harder to access from other JS files.";
console.log(link);  // OK
console.log(window.link);  // undefined (GOOD!)
console.log(window.button);  // OK

5. क्लोजर के साथ आसान उपयोग:var लूप के अंदर क्लोजर के साथ घोषित चर के साथ अच्छी तरह से काम नहीं करते हैं। यहां एक सरल लूप है जो उन मानों के अनुक्रम को आउटपुट करता है iजो समय में विभिन्न बिंदुओं पर चर होते हैं:

for (let i = 0; i < 5; i++) {
    console.log(`i is ${i}`), 125/*ms*/);
}

विशेष रूप से, यह आउटपुट:

i is 0
i is 1
i is 2
i is 3
i is 4

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

for (let i = 0; i < 5; i++) {
    setTimeout(_ => console.log(`i is ${i}`), 125/*ms*/);
}

... जब तक हम साथ रहेंगे तब तक आउटपुट अपरिवर्तित रहता है let। इसके विपरीत, अगर हमने var iइसके बजाय उपयोग किया था :

for (var i = 0; i < 5; i++) {
    setTimeout(_ => console.log(`i is ${i}`), 125/*ms*/);
}

... लूप अप्रत्याशित रूप से आउटपुट "मैं 5" पांच बार है:

i is 5
i is 5
i is 5
i is 5
i is 5

5
# 5 एक दौड़ की स्थिति के कारण नहीं है। के varबजाय का उपयोग करके let, कोड के बराबर है: var i = 0; while (i < 5) { doSomethingLater(); i++; } iक्लोजर के बाहर है, और जब तक doSomethingLater()निष्पादित किया जाता है, iतब तक 5 बार पहले ही वृद्धि की जा चुकी है, इसलिए आउटपुट i is 5पांच गुना है। उपयोग करके let, चर iबंद होने के भीतर है, इसलिए प्रत्येक async कॉल iको 'वैश्विक' के साथ उपयोग करने के बजाय इसकी अपनी प्रति मिलती है var
डैनियल टी।

@ डैनियल टी।: मुझे नहीं लगता कि लूप इनिशियलाइज़र से परिवर्तनशील परिभाषा को उठाने का परिवर्तन कुछ भी बताता है। यह बस शब्दार्थ की सामान्य परिभाषा है for। एक अधिक सटीक परिवर्तन, हालांकि अधिक जटिल है, शास्त्रीय for (var i = 0; i < 5; i++) { (function(j) { setTimeout(_ => console.log(मैं $ {j} है ), 125/*ms*/); })(i); }जो फ़ंक्शन iके jअंदर के नाम के साथ प्रत्येक मूल्य को बचाने के लिए "फ़ंक्शन-सक्रियण रिकॉर्ड" का परिचय देता है।
मोर्मगिल

14

निम्नलिखित दो कार्यों में अंतर दिखाई दे सकता है:

function varTest() {
    var x = 31;
    if (true) {
        var x = 71;  // Same variable!
        console.log(x);  // 71
    }
    console.log(x);  // 71
}

function letTest() {
    let x = 31;
    if (true) {
        let x = 71;  // Different variable
        console.log(x);  // 71
    }
    console.log(x);  // 31
}

13

let दिलचस्प है, क्योंकि यह हमें ऐसा कुछ करने की अनुमति देता है:

(() => {
    var count = 0;

    for (let i = 0; i < 2; ++i) {
        for (let i = 0; i < 2; ++i) {
            for (let i = 0; i < 2; ++i) {
                console.log(count++);
            }
        }
    }
})();

जिसके परिणामस्वरूप गिनती [0, 7] होती है।

जहाँ तक

(() => {
    var count = 0;

    for (var i = 0; i < 2; ++i) {
        for (var i = 0; i < 2; ++i) {
            for (var i = 0; i < 2; ++i) {
                console.log(count++);
            }
        }
    }
})();

केवल गिना जाता है [0, 1]।


2
यह पहली बार है जब मैंने कभी किसी को चर छाया की तरह काम करते देखा है वह वांछनीय था। नहीं, चलो का उद्देश्य छायांकन को सक्षम करने के लिए नहीं है
जॉन हौगलैंड

1
उद्देश्य? यह एक निर्माण है, आप इसका उपयोग कर सकते हैं लेकिन कृपया, दिलचस्प तरीकों में से एक यह है।
दिमित्री

13

VS ब्लॉक गुंजाइश:

के बीच मुख्य अंतर varऔर letहै कि चर के साथ घोषित है varकर रहे हैं समारोह scoped । जबकि कार्यों के साथ घोषित letकर रहे हैं ब्लॉक scoped । उदाहरण के लिए:

function testVar () {
  if(true) {
    var foo = 'foo';
  }

  console.log(foo);
}

testVar();  
// logs 'foo'


function testLet () {
  if(true) {
    let bar = 'bar';
  }

  console.log(bar);
}

testLet(); 
// reference error
// bar is scoped to the block of the if statement 

इसके साथ चर var:

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

इसके साथ चर let:

जब दूसरे फ़ंक्शन testLetको वैरिएबल बार कहा जाता है, जिसके साथ घोषित किया जाता है let, केवल ifकथन के अंदर पहुंच योग्य होता है । क्योंकि चर के साथ घोषित letकर रहे हैं ब्लॉक scoped (जहां एक ब्लॉक कर्ली कोष्ठक के बीच कोड है जैसे if{}, for{}, function{})।

let चर नहीं फहराया जाता है:

बीच एक और अंतर varऔर letसाथ साथ घोषित चर है let फहराया नहीं मिलता । एक उदाहरण इस व्यवहार को चित्रित करने का सबसे अच्छा तरीका है:

चर let नहीं फहराया जाता है:

console.log(letVar);

let letVar = 10;
// referenceError, the variable doesn't get hoisted

साथ चर var करते प्राप्त फहराया:

console.log(varVar);

var varVar = 10;
// logs undefined, the variable gets hoisted

ग्लोबल से letजुड़ी नहीं है window:

letवैश्विक दायरे में घोषित किया गया एक चर (जो एक फ़ंक्शन में कोड नहीं है) वैश्विक windowऑब्जेक्ट पर एक संपत्ति के रूप में जोड़ा नहीं जाता है । उदाहरण के लिए (यह कोड वैश्विक दायरे में है):

var bar = 5;
let foo  = 10;

console.log(bar); // logs 5
console.log(foo); // logs 10

console.log(window.bar);  
// logs 5, variable added to window object

console.log(window.foo);
// logs undefined, variable not added to window object


कब letइस्तेमाल किया जाना चाहिए var?

का प्रयोग करें letअधिक varजब भी आप क्योंकि यह केवल अधिक विशिष्ट दायरे वाला कर सकते हैं। यह संभावित नामकरण संघर्ष को कम करता है जो बड़ी संख्या में चर के साथ काम करते समय हो सकता है। varका उपयोग तब किया जा सकता है जब आप स्पष्ट रूप से windowऑब्जेक्ट पर एक वैश्विक चर चाहते हैं (हमेशा ध्यान से विचार करें यदि यह वास्तव में आवश्यक है)।


9

यह भी प्रकट होता है कि, कम से कम विज़ुअल स्टूडियो 2015 में टाइपस्क्रिप्ट 1.5, "var" एक ब्लॉक में एक ही चर नाम की कई घोषणाओं की अनुमति देता है, और "चलो" नहीं करता है।

यह एक संकलन त्रुटि उत्पन्न नहीं करेगा:

var x = 1;
var x = 2;

यह करेगा:

let x = 1;
let x = 2;

9

var वैश्विक गुंजाइश (लहरा-सक्षम) चर है।

letऔर constब्लॉक स्कोप है।

test.js

{
    let l = 'let';
    const c = 'const';
    var v = 'var';
    v2 = 'var 2';
}

console.log(v, this.v);
console.log(v2, this.v2);
console.log(l); // ReferenceError: l is not defined
console.log(c); // ReferenceError: c is not defined


8

उपयोग करते समय let

letकीवर्ड (आमतौर पर एक जो कुछ भी ब्लॉक के दायरे को चर घोषणा देता { .. }जोड़ी) उसमें शामिल है। दूसरे शब्दों में,let परोक्ष अपनी चर घोषणा के लिए किसी भी ब्लॉक की गुंजाइश hijacks।

letचर को windowऑब्जेक्ट में एक्सेस नहीं किया जा सकता क्योंकि वे वैश्विक रूप से एक्सेस नहीं किए जा सकते।

function a(){
    { // this is the Max Scope for let variable
        let x = 12;
    }
    console.log(x);
}
a(); // Uncaught ReferenceError: x is not defined

उपयोग करते समय var

var और ES5 में चर कार्यों में स्कोप है जिसका अर्थ है कि चर फ़ंक्शन के भीतर मान्य हैं और फ़ंक्शन के बाहर नहीं।

varचर को windowऑब्जेक्ट में एक्सेस किया जा सकता है क्योंकि वे वैश्विक रूप से एक्सेस नहीं किए जा सकते हैं।

function a(){ // this is the Max Scope for var variable
    { 
        var x = 12;
    }
    console.log(x);
}
a(); // 12

यदि आप अधिक जानना चाहते हैं तो नीचे पढ़ना जारी रखें

गुंजाइश पर सबसे प्रसिद्ध साक्षात्कार प्रश्नों में से एक भी नीचे letऔर varनीचे के सटीक उपयोग को पर्याप्त कर सकता है ;

उपयोग करते समय let

for (let i = 0; i < 10 ; i++) {
    setTimeout(
        function a() {
            console.log(i); //print 0 to 9, that is literally AWW!!!
        }, 
        100 * i);
}

इसका उपयोग करते समय ऐसा होता है let , प्रत्येक लूप पुनरावृत्ति के लिए चर को स्कोप किया जाता है और इसकी अपनी प्रति होती है।

उपयोग करते समय var

for (var i = 0; i < 10 ; i++) {
    setTimeout(
        function a() {
            console.log(i); //print 10 times 10
        }, 
        100 * i);
}

ऐसा इसलिए है क्योंकि उपयोग करते समय var, प्रत्येक लूप पुनरावृत्ति के लिए चर को स्कैन किया जाता है और इसकी प्रतिलिपि साझा की जाती है।


7

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

var SomeConstructor;

{
    let privateScope = {};

    SomeConstructor = function SomeConstructor () {
        this.someProperty = "foo";
        privateScope.hiddenProperty = "bar";
    }

    SomeConstructor.prototype.showPublic = function () {
        console.log(this.someProperty); // foo
    }

    SomeConstructor.prototype.showPrivate = function () {
        console.log(privateScope.hiddenProperty); // bar
    }

}

var myInstance = new SomeConstructor();

myInstance.showPublic();
myInstance.showPrivate();

console.log(privateScope.hiddenProperty); // error

देखें ' निजी इंटरफेस का अनुकरण '


क्या आप इस बात की विस्तृत जानकारी दे सकते हैं कि तत्काल लागू फंक्शन एक्सप्रेशन "कोड सुरक्षा" और letक्या प्रदान नहीं करते हैं ? (मुझे लगता है कि आप "आत्म आह्वान समारोह" के साथ IIFE मतलब है।)
रॉबर्ट सिएमर

और आप hiddenPropertyकंस्ट्रक्टर में क्यों सेट करते हैं ? hiddenPropertyआपके "वर्ग" में सभी उदाहरणों के लिए केवल एक ही है ।
राबर्ट सीमर

5

सबसे बुनियादी शब्दों में,

for (let i = 0; i < 5; i++) {
  // i accessible ✔️
}
// i not accessible ❌

for (var i = 0; i < 5; i++) {
  // i accessible ✔️
}
// i accessible ✔️

↓ सैंडबॉक्स चारों ओर खेलने के लिए play

संपादित करें बनाम var


4

कुछ हैक्स के साथ let:

1।

    let statistics = [16, 170, 10];
    let [age, height, grade] = statistics;

    console.log(height)

2।

    let x = 120,
    y = 12;
    [x, y] = [y, x];
    console.log(`x: ${x} y: ${y}`);

3।

    let node = {
                   type: "Identifier",
                   name: "foo"
               };

    let { type, name, value } = node;

    console.log(type);      // "Identifier"
    console.log(name);      // "foo"
    console.log(value);     // undefined

    let node = {
        type: "Identifier"
    };

    let { type: localType, name: localName = "bar" } = node;

    console.log(localType);     // "Identifier"
    console.log(localName);     // "bar"

गेट्टर और सेटर let:

let jar = {
    numberOfCookies: 10,
    get cookies() {
        return this.numberOfCookies;
    },
    set cookies(value) {
        this.numberOfCookies = value;
    }
};

console.log(jar.cookies)
jar.cookies = 7;

console.log(jar.cookies)

कृपया इसका क्या मतलब है let { type, name, value } = node;? आप 3 गुण प्रकार / नाम / मान के साथ एक नई वस्तु बनाते हैं और नोड से गुण मान के साथ उन्हें प्रारंभ करते हैं?
AlainIb

उदाहरण 3 में आप फिर से नोड घोषित कर रहे हैं जो अपवाद का कारण बनता है। ये सभी उदाहरण भी पूरी तरह से काम करते varहैं।
रेहान हैदर

4

चलो बनाम। यह सब गुंजाइश की बात है

वैरिएबल वैश्विक हैं और मूल रूप से हर जगह पहुंच सकते हैं, जबकि वैरिएबल वैश्विक नहीं हैं और केवल तब तक मौजूद हैं जब तक कि समापन कोष्ठक उन्हें मार नहीं देता।

नीचे मेरा उदाहरण देखें, और ध्यान दें कि शेर (लेट) वेरिएबल दो कंसोल में कैसे कार्य करता है। यह 2 के क्षेत्र में दायरे से बाहर हो जाता है।

var cat = "cat";
let dog = "dog";

var animals = () => {
    var giraffe = "giraffe";
    let lion = "lion";

    console.log(cat);  //will print 'cat'.
    console.log(dog);  //will print 'dog', because dog was declared outside this function (like var cat).

    console.log(giraffe); //will print 'giraffe'.
    console.log(lion); //will print 'lion', as lion is within scope.
}

console.log(giraffe); //will print 'giraffe', as giraffe is a global variable (var).
console.log(lion); //will print UNDEFINED, as lion is a 'let' variable and is now out of scope.

4

ES6 ने var के लिए दो नए कीवर्ड ( लेट और कास्ट ) को प्रस्तुत किया ।

जब आपको ब्लॉक स्तर की मंदी की आवश्यकता होती है तो आप var के बजाय let और const के साथ जा सकते हैं।

नीचे दी गई तालिका var, let और const के बीच के अंतर को संक्षेप में बताती है

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


3

आज्ञा देना es6 का एक हिस्सा है। ये कार्य आसान तरीके से अंतर की व्याख्या करेंगे।

function varTest() {
  var x = 1;
  if (true) {
    var x = 2;  // same variable!
    console.log(x);  // 2
  }
  console.log(x);  // 2
}

function letTest() {
  let x = 1;
  if (true) {
    let x = 2;  // different variable
    console.log(x);  // 2
  }
  console.log(x);  // 1
}

3

नीचे दिखाया गया है कि कैसे 'let' और 'var' क्षेत्र में भिन्न हैं:

let gfoo = 123;
if (true) {
    let gfoo = 456;
}
console.log(gfoo); // 123

var hfoo = 123;
if (true) {
    var hfoo = 456;
}
console.log(hfoo); // 456

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

जबकि hfoo, द्वारा परिभाषित किया गया varहै, शुरू में वैश्विक दायरे में है , लेकिन फिर से जब हम इसे अंदर घोषित करते हैं if clause, तो यह वैश्विक गुंजाइश को hfoo मानता है, हालांकि इसे घोषित करने के लिए var का उपयोग फिर से किया गया है। और जब हम इसके मूल्य को फिर से असाइन करते हैं तो हम देखते हैं कि वैश्विक गुंजाइश hfoo भी प्रभावित होती है। यह प्राथमिक अंतर है।


2

जैसा कि ऊपर उल्लेख किया गया है:

अंतर डांट रहा है। varनिकटतम के दायरे वाला समारोह ब्लॉक और letके दायरे वाला निकटतम संलग्न ब्लॉक है, जो एक समारोह ब्लॉक की तुलना में छोटे हो सकता है। यदि कोई ब्लॉक के बाहर दोनों वैश्विक हैं। एक उदाहरण देखें:

उदाहरण 1:

मेरे दोनों उदाहरणों में मेरा एक कार्य है myfuncmyfuncएक चर के myvarबराबर होता है 10. मेरे पहले उदाहरण में मैं myvarजांचता हूं कि क्या 10 ( myvar==10) के बराबर है । यदि हाँ, तो मैं कीवर्ड myvarका उपयोग करते हुए एक चर (अब मेरे पास दो myvar चर) घोषित करता हूं varऔर इसे एक नया मान (20) असाइन करता हूं । अगली पंक्ति में मैं अपने कंसोल पर इसका मूल्य प्रिंट करता हूं। सशर्त ब्लॉक के बाद मैं फिर से myvarअपने कंसोल के मूल्य को प्रिंट करता हूं। यदि आप के आउटपुट को देखते हैं myfunc, तो myvarमान 20 के बराबर है।

कीवर्ड दें

Example2: मेरे दूसरे उदाहरण varमें मेरे सशर्त ब्लॉक में कीवर्ड का उपयोग करने के बजाय मैं कीवर्ड myvarका उपयोग करने की घोषणा करता हूं let। अब जब मैं फोन करता myfunc हूं तो मुझे दो अलग-अलग आउटपुट मिलते हैं: myvar=20और myvar=10

तो अंतर बहुत सरल है यानी इसका दायरा।


3
कृपया कोड की तस्वीरें पोस्ट न करें, यह SO पर बुरा व्यवहार माना जाता है क्योंकि यह भविष्य के उपयोगकर्ताओं (साथ ही पहुंच संबंधी चिंताओं) के लिए खोज योग्य नहीं होगा। साथ ही, यह उत्तर कुछ भी नहीं जोड़ता है कि अन्य उत्तर पहले से ही संबोधित नहीं किए गए हैं।
इनोस्टिया

2

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

एक निष्पादन संदर्भ के निर्माण चरण के दौरान, var, let और const अभी भी दिए गए निष्पादन संदर्भ के चर पर्यावरण में एक अपरिभाषित मूल्य के साथ स्मृति में अपने चर को संग्रहीत करेंगे। अंतर निष्पादन चरण में है। यदि आप किसी मान को निर्दिष्ट करने से पहले चर के साथ परिभाषित चर का संदर्भ लेते हैं, तो यह अपरिभाषित होगा। कोई अपवाद नहीं उठाया जाएगा।

हालाँकि, आप घोषित या कास्ट के साथ घोषित चर का संदर्भ तब तक नहीं दे सकते, जब तक कि यह घोषित न हो जाए। यदि आप इसे घोषित करने से पहले उपयोग करने का प्रयास करते हैं, तो अपवाद के निष्पादन के चरण के दौरान एक अपवाद उठाया जाएगा। अब चर अभी भी स्मृति में होगा, निर्माण के संदर्भ के निर्माण चरण के सौजन्य से, लेकिन इंजन आपको इसका उपयोग करने की अनुमति नहीं देगा:

function a(){
    b;
    let b;
}
a();
> Uncaught ReferenceError: b is not defined

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

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

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

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


2

मुझे लगता है कि शर्तें और अधिकांश उदाहरण थोड़ा भारी हैं, मुख्य मुद्दा जो मैंने व्यक्तिगत रूप से अंतर के साथ समझा था कि "ब्लॉक" क्या है। कुछ बिंदु पर मुझे एहसास हुआ, एक खंड IFकथन के अलावा किसी भी घुंघराले कोष्ठक होगा । किसी {फ़ंक्शन या लूप का एक ओपनिंग ब्रैकेट एक नए ब्लॉक को परिभाषित करेगा, इसके साथ परिभाषित कुछ भी let, }एक ही चीज़ (फ़ंक्शन या लूप) के समापन ब्रैकेट के बाद उपलब्ध नहीं होगा ; इसे ध्यान में रखते हुए, यह समझना आसान था:

let msg = "Hello World";

function doWork() { // msg will be available since it was defined above this opening bracket!
  let friends = 0;
  console.log(msg);

  // with VAR though:
  for (var iCount2 = 0; iCount2 < 5; iCount2++) {} // iCount2 will be available after this closing bracket!
  console.log(iCount2);
  
    for (let iCount1 = 0; iCount1 < 5; iCount1++) {} // iCount1 will not be available behind this closing bracket, it will return undefined
  console.log(iCount1);
  
} // friends will no be available after this closing bracket!
doWork();
console.log(friends);


1

अब मुझे लगता है कि उपयोग करने वाले बयानों के ब्लॉक में चर का बेहतर स्कोपिंग है let:

function printnums()
{
    // i is not accessible here
    for(let i = 0; i <10; i+=)
    {
       console.log(i);
    }
    // i is not accessible here

    // j is accessible here
    for(var j = 0; j <10; j++)
    {
       console.log(j);
    }
    // j is accessible here
}

मुझे लगता है कि लोग यहाँ के बाद का उपयोग करना शुरू कर देंगे ताकि वे जावास्क्रिप्ट में अन्य भाषाओं, जावा, सी #, आदि की तरह ही स्कूपिंग करेंगे।

जावास्क्रिप्ट में स्कोपिंग के बारे में स्पष्ट समझ नहीं रखने वाले लोग पहले गलती करते थे।

उत्थापन का उपयोग करके समर्थित नहीं है let

इस दृष्टिकोण के साथ जावास्क्रिप्ट में मौजूद त्रुटियों को हटाया जा रहा है।

गहराई में ES6 का संदर्भ लें : इसे बेहतर ढंग से समझने के लिए कांस्ट करें।


इसके लिए गहराई से समझने के लिए लिंक देखें - davidwalsh.name/for-and-against-let
swaraj patil

1

यह लेख स्पष्ट रूप से var, let और const के बीच के अंतर को परिभाषित करता है

const एक संकेत है कि पहचानकर्ता को फिर से असाइन नहीं किया जाएगा।

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

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

https://medium.com/javascript-scene/javascript-es6-var-let-or-const-ba58b8dcde75#.esmkpbg9b

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