सवाल जावास्क्रिप्ट में एक चर घोषित करने के लिए "let" और "var" का उपयोग करने के बीच क्या अंतर है?


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

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


3259
2018-04-17 20:09


मूल


ईसीएमएस्क्रिप्ट मानक है और let में शामिल है 6 वें संस्करण का मसौदा और सबसे अधिक संभावना अंतिम विनिर्देश में होगा। - Richard Ayotte
देख kangax.github.io/es5-compat-table/es6 ईएस 6 विशेषताओं (चलो समेत) के अप टू डेट समर्थन मैट्रिक्स के लिए। फ़ायरफ़ॉक्स लिखने के समय, क्रोम और आईई 11 सभी इसका समर्थन करते हैं (हालांकि मुझे विश्वास है कि एफएफ का कार्यान्वयन काफी मानक नहीं है)। - Nico Burns
सबसे लंबे समय तक मुझे नहीं पता था कि फॉर लूप में वर्रों को उस समारोह में डांटा गया था जो इसे लपेटा गया था। मुझे याद है कि पहली बार यह पता लग रहा था और सोचा कि यह बहुत बेवकूफ था। मुझे कुछ शक्ति दिखाई देती है, हालांकि अब यह जानकर कि दोनों को अलग-अलग कारणों से कैसे इस्तेमाल किया जा सकता है और कुछ मामलों में आप वास्तव में लूप के लिए एक var का उपयोग करना चाहते हैं और यह ब्लॉक पर नहीं है। - Eric Bishard
चूंकि ES6 सुविधा समर्थन में सुधार होता है, ES6 गोद लेने से संबंधित प्रश्न फीचर समर्थन से प्रदर्शन अंतरों पर ध्यान केंद्रित करता है। जैसे की, यहां एक साइट है जिसे मैंने ES6 और ES5 के बीच प्रदर्शन अंतर को बेंचमार्क किया। ध्यान रखें कि यह समय के साथ बदल जाएगा क्योंकि इंजन ES6 कोड के लिए ऑप्टिमाइज़ करते हैं। - timolawl
यह एक बहुत अच्छी पढ़ाई है wesbos.com/javascript-scoping - onmyway133


जवाब:


अंतर गुंजाइश है। var निकटतम फ़ंक्शन ब्लॉक पर स्कॉप्ड किया गया है और let निकटतम के लिए scoped है संलग्नित ब्लॉक, जो फ़ंक्शन ब्लॉक से छोटा हो सकता है। यदि किसी भी ब्लॉक के बाहर दोनों ग्लोबल हैं।

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

डेमो: 

var html = '';

write('#### global ####\n');
write('globalVar: ' + globalVar); //undefined, but visible

try {
  write('globalLet: ' + globalLet); //undefined, *not* visible
} catch (exception) {
  write('globalLet: exception');
}

write('\nset variables');

var globalVar = 'globalVar';
let globalLet = 'globalLet';

write('\nglobalVar: ' + globalVar);
write('globalLet: ' + globalLet);

function functionScoped() {
  write('\n#### function ####');
  write('\nfunctionVar: ' + functionVar); //undefined, but visible

  try {
    write('functionLet: ' + functionLet); //undefined, *not* visible
  } catch (exception) {
    write('functionLet: exception');
  }

  write('\nset variables');

  var functionVar = 'functionVar';
  let functionLet = 'functionLet';

  write('\nfunctionVar: ' + functionVar);
  write('functionLet: ' + functionLet);
}

function blockScoped() {
  write('\n#### block ####');
  write('\nblockVar: ' + blockVar); //undefined, but visible

  try {
    write('blockLet: ' + blockLet); //undefined, *not* visible
  } catch (exception) {
    write('blockLet: exception');
  }

  for (var blockVar = 'blockVar', blockIndex = 0; blockIndex < 1; blockIndex++) {
    write('\nblockVar: ' + blockVar); // visible here and whole function
  };

  for (let blockLet = 'blockLet', letIndex = 0; letIndex < 1; letIndex++) {
    write('blockLet: ' + blockLet); // visible only here
  };

  write('\nblockVar: ' + blockVar);

  try {
    write('blockLet: ' + blockLet); //undefined, *not* visible
  } catch (exception) {
    write('blockLet: exception');
  }
}

function write(line) {
  html += (line ? line : '') + '<br />';
}

functionScoped();
blockScoped();

document.getElementById('results').innerHTML = html;
<pre id="results"></pre>

ग्लोबल:

फ़ंक्शन ब्लॉक के बाहर इस तरह उपयोग किए जाने पर वे बहुत समान होते हैं।

let me = 'go';  // globally scoped
var i = 'able'; // globally scoped

हालांकि, वैश्विक चर के साथ परिभाषित किया गया है let वैश्विक पर गुणों के रूप में नहीं जोड़ा जाएगा window उनके साथ परिभाषित की तरह वस्तु var

console.log(window.me); // undefined
console.log(window.i); // 'able'

समारोह:

फ़ंक्शन ब्लॉक में इस तरह उपयोग किए जाने पर वे समान होते हैं।

function ingWithinEstablishedParameters() {
    let terOfRecommendation = 'awesome worker!'; //function block scoped
    var sityCheerleading = 'go!'; //function block scoped
}

ब्लॉक:

यहां अंतर है। let केवल में दिखाई देता है for() लूप और var पूरे समारोह के लिए दृश्यमान है।

function allyIlliterate() {
    //tuce is *not* visible out here

    for( let tuce = 0; tuce < 5; tuce++ ) {
        //tuce is only visible in here (and in the for() parentheses)
        //and there is a separate tuce variable for each iteration of the loop
    }

    //tuce is *not* visible out here
}

function byE40() {
    //nish *is* visible out here

    for( var nish = 0; nish < 5; nish++ ) {
        //nish is visible to the whole function
    }

    //nish *is* visible out here
}

पुन: घोषणा:

सख्त मोड मानते हुए, var आपको उसी वैरिएबल में एक ही चर को फिर से घोषित करने देगा। दूसरी ओर, let नहीं होगा:

'use strict';
let me = 'foo';
let me = 'bar'; // SyntaxError: Identifier 'me' has already been declared
'use strict';
var me = 'foo';
var me = 'bar'; // No problem, `me` is replaced.

4571
2018-05-27 10:16



तो क्या किसी निश्चित ब्लॉक में आवश्यक होने पर केवल स्मृति को खाली करने का बयान देना है? - NoBugs
@ नोबग्स, हां, और यह प्रोत्साहित किया जाता है कि चर केवल अस्तित्व में हैं जहां उनकी आवश्यकता है। - batman
let ब्लॉक अभिव्यक्ति let (variable declaration) statement गैर मानक है और भविष्य में हटा दिया जाएगा, bugzilla.mozilla.org/show_bug.cgi?id=1023609। - Gajus
वैश्विक स्तर पर उनका अंतर है: let वैश्विक चर में संपत्ति जोड़ें मत 2ality.com/2015/02/es6-scoping.html#the_global_object - Yukulélé
@ थिंकिंगस्टिफ़: कृपया समीक्षा करें यह मेटा पोस्ट, और उठाए गए तकनीकी मुद्दों पर वजन। - Robert Harvey♦


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

डेमो

for(var i = 1; i < 6; i++) {
  document.getElementById('my-element' + i)
    .addEventListener('click', function() { alert(i) })
}

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

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

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

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

'use strict';

for(let i = 1; i < 6; i++) {
  document.getElementById('my-element' + i)
    .addEventListener('click', function() { alert(i) })
}

451
2018-04-17 20:11



यह वास्तव में अच्छा है। मैं अपेक्षा करता हूं कि "i" को लूप बॉडी के बाहर परिभाषित किया जाए, जिसमें ब्रैकेट्स के भीतर और "i" के आस-पास "बंद" न हो। निश्चित रूप से आपका उदाहरण अन्यथा साबित होता है। मुझे लगता है कि यह वाक्यविन्यास बिंदु से थोड़ा उलझन में है लेकिन यह परिदृश्य इतना आम है कि इसे इस तरह समर्थन करने के लिए समझ में आता है। इसे लाने के लिए बहुत धन्यवाद। - Karol Kolenda
आईई 11 का समर्थन करता है let, लेकिन यह सभी बटनों के लिए "6" अलर्ट करता है। क्या आपके पास कोई स्रोत कह रहा है कि कैसे let व्यवहार करना चाहिए? - Jim Hunziker
ऐसा लगता है कि आपका जवाब सही व्यवहार है: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/... - Jim Hunziker
दरअसल यह जावास्क्रिप्ट में एक आम गड़बड़ है और अब मैं देख सकता हूं क्यों let वास्तव में उपयोगी होगा। एक लूप में ईवेंट श्रोताओं को सेट करने के लिए अब स्थानीय रूप से स्कॉइंग के लिए तत्काल रूप से लागू फ़ंक्शन अभिव्यक्ति की आवश्यकता नहीं होती है i प्रत्येक पुनरावृत्ति पर। - Adrian Moisa
"चलो" का उपयोग सिर्फ इस समस्या को रोकता है। इसलिए प्रत्येक पुनरावृत्ति एक निजी स्वतंत्र ब्लॉक स्कोप बनाता है, लेकिन "i" चर अभी भी ब्लॉक के बाद के परिवर्तनों से दूषित हो सकता है, (इटेटरेटर वैरिएबल दिया गया है आमतौर पर ब्लॉक के भीतर बदल दिया गया है, लेकिन ब्लॉक के भीतर अन्य घोषित वैरिएबल भी हो सकते हैं) और ब्लॉक के भीतर घोषित किए गए किसी भी फ़ंक्शन को ब्लॉक के दौरान घोषित अन्य कार्यों के लिए "i" के मान को दूषित कर सकता है क्योंकि वे कर उसी निजी ब्लॉक स्कोप को साझा करें, इसलिए "i" के समान संदर्भ। - gary


यहाँ एक है की व्याख्या let कीवर्ड कुछ उदाहरणों के साथ।

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

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

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


131
2018-02-23 18:35



लिंक किए गए दस्तावेज़ से टेक्स्ट का मुख्य हिस्सा प्रतीत होता है, "var var की तरह बहुत काम करता है। मुख्य अंतर यह है कि एक var चर का दायरा संपूर्ण संलग्न कार्य है"। - Michael Burr
हालांकि यह तकनीकी रूप से सही कहने के लिए सही है कि आईई इसका समर्थन नहीं करता है, यह कहना सही है कि यह एक मोज़िला केवल विस्तार है। - olliej
@olliej, वास्तव में मोज़िला खेल से आगे है। पृष्ठ 1 9 देखें ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf - Tyler Crompton
@ टायलर क्रॉम्प्टन जो सिर्फ उन शब्दों का सेट है जो वर्षों से आरक्षित हैं। जब मोज़िला जोड़ा गया तो यह पूरी तरह से एक मोज़िला विस्तार था, जिसमें कोई संबंधित नमूना नहीं था। ईएस 6 को बयान बयान के लिए व्यवहार परिभाषित करना चाहिए, लेकिन मोज़िला ने वाक्यविन्यास पेश करने के बाद यह आया था। याद रखें कि मोज़े में ई 4 एक्स भी है, जो पूरी तरह से मर चुका है और केवल मोज़ है। - olliej
आईई 11 के लिए समर्थन जोड़ा गया let  msdn.microsoft.com/en-us/library/ie/dn342892%28v=vs.85%29.aspx - eloyesp


के बीच क्या अंतर है 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 बयान।

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

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

आज, 8 जून 2018, अभी भी कुछ ब्राउज़र हैं जो समर्थन नहीं करते हैं let!

enter image description here


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

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


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

(**) ब्लॉक स्कॉप्ड वेरिएबल नहीं फंस गए हैं


116
2018-06-02 20:59



उत्तर v4 के संबंध में: i फंक्शन-ब्लॉक में हर जगह जाना जाता है! यह शुरू होता है undefined (hoisting के कारण) जब तक आप एक मूल्य असाइन नहीं करते! पुनश्च: let भी फहराया जाता है (इसके ब्लॉक के शीर्ष पर), लेकिन एक दे देंगे ReferenceError जब पहली असाइनमेंट से पहले ब्लॉक में संदर्भित किया गया था। (ps2: मैं एक समर्थक अर्धविराम दयालु लड़का हूं लेकिन आपको वास्तव में ब्लॉक के बाद अर्धविराम की आवश्यकता नहीं है)। कहा जा रहा है, समर्थन के संबंध में वास्तविकता-जांच जोड़ने के लिए धन्यवाद! - GitaarLAB
@ गीतार्लब: के अनुसार मोज़िला डेवलपर नेटवर्क : "ईसीएमएस्क्रिप्ट 2015 में, बाइंडिंग वेरिएबल होस्टिंग के अधीन नहीं हैं, जिसका अर्थ यह है कि घोषणाओं को वर्तमान निष्पादन संदर्भ के शीर्ष पर नहीं जाना चाहिए।" - वैसे भी, मैंने अपने जवाब में कुछ सुधार किए हैं जो कि होस्टिंग व्यवहार में अंतर को स्पष्ट करना चाहिए let तथा var! - John Slegers
आपके उत्तर में बहुत सुधार हुआ (मैंने पूरी तरह से जांच की)। ध्यान दें कि आपकी टिप्पणी में संदर्भित एक ही लिंक में यह भी कहा गया है: "(चलो) वैरिएबल एक" अस्थायी मृत क्षेत्र "में है ब्लॉक की शुरुआत जब तक प्रारंभिक प्रक्रिया संसाधित नहीं हो जाती है। "इसका मतलब है कि 'पहचानकर्ता' (टेक्स्ट-स्ट्रिंग 'आरक्षित' को 'कुछ' पर इंगित करने के लिए) पहले से ही है प्रासंगिक दायरे में आरक्षित, अन्यथा यह रूट / होस्ट / विंडो स्कोप का हिस्सा बन जाएगा। मेरे लिए व्यक्तिगत रूप से, 'होस्टिंग' का अर्थ घोषित 'पहचानकर्ताओं' को उनके प्रासंगिक दायरे में आरक्षित / लिंक करने से अधिक कुछ नहीं है; उनके प्रारंभिक / असाइनमेंट / संशोधनीयता को छोड़कर! - GitaarLAB
और .. + 1। आपके द्वारा लिंक किया गया कि केली सिम्पसन लेख एक है अति उत्कृष्ट पढ़ें, इसके लिए धन्यवाद! यह "अस्थायी मृत क्षेत्र" उर्फ ​​"टीडीजेड" के बारे में भी स्पष्ट है। एक दिलचस्प बात जो मैं जोड़ना चाहता हूं: मैंने एमडीएन पर पढ़ा है let तथा const थे केवल तभी उपयोग करने की अनुशंसा की जाती है जब आपको वास्तव में उनकी अतिरिक्त कार्यक्षमता की आवश्यकता हो, क्योंकि इन अतिरिक्त सुविधाओं को लागू / जांचना (जैसे केवल लिखने के लिए) परिणामस्वरूप (वर्तमान) इंजन (ओं) के लिए लागू / चेक / सत्यापन / सेटअप के लिए 'अधिक काम' (और दायरे के पेड़ में अतिरिक्त स्कोप-नोड्स) में परिणाम । - GitaarLAB


स्वीकृत उत्तर में एक बिंदु गुम है:

{
  let a = 123;
};

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

98
2018-04-17 21:38



स्वीकृत उत्तर इस बिंदु को बताता है। - TM.
स्वीकार्य उत्तर इस बिंदु को इसके उदाहरण में नहीं समझाता है। स्वीकार्य उत्तर ने इसे केवल एक में प्रदर्शित किया for लूप प्रारंभकर्ता, नाटकीय रूप से सीमाओं के आवेदन के दायरे को सीमित कर रहा है let। Upvoted। - Jon Davis
@ stimpy77 यह स्पष्ट रूप से कहता है "चलो निकटतम संलग्न ब्लॉक पर चले गए"; क्या हर तरह से प्रकट होने की आवश्यकता है? - Dave Newton
वहां बहुत सारे उदाहरण थे और उनमें से कोई भी इस मामले को सही ढंग से प्रदर्शित नहीं करता था .. मैंने दोनों स्वीकृत उत्तर और इस दोनों को उखाड़ फेंक दिया होगा? - Jon Davis
यह योगदान दर्शाता है कि एक "ब्लॉक" बस ब्रैकेट में संलग्न लाइनों का एक सेट हो सकता है; यानी किसी भी प्रकार के नियंत्रण प्रवाह, लूप इत्यादि से जुड़े होने की आवश्यकता नहीं है। - webelo


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

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

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


40
2018-03-06 10:41



यह भी ध्यान देने योग्य है कि ईसीएमएस्क्रिप्ट मानक है और let में शामिल है 6 वें संस्करण का मसौदा और सबसे अधिक संभावना अंतिम विनिर्देश में होगा। - Richard Ayotte
यह अंतर 3 साल बनाता है: डी - olliej
बस इस प्रश्न में छेड़छाड़ की और 2012 में यह अभी भी मामला है कि केवल मोज़िला ब्राउज़र ही समर्थन करते हैं let। सफारी, आईई, और चोम सभी नहीं करते हैं। - pseudosavant
आकस्मिक रूप से दुर्घटना पर आंशिक ब्लॉक गुंजाइश बनाने का विचार एक अच्छा मुद्दा है, सावधान रहें, let एक द्वारा परिभाषित एक चर का उपयोग करने के लिए, उछाल नहीं है let आपके ब्लॉक के शीर्ष पर परिभाषित किया गया। यदि आपके पास है if कथन जो कोड की केवल कुछ पंक्तियों से अधिक है, आप भूल सकते हैं कि जब तक इसे परिभाषित नहीं किया जाता है तब तक आप उस चर का उपयोग नहीं कर सकते। महान अंक !!! - Eric Bishard
@EricB: हाँ और नहीं: "ईसीएमएस्क्रिप्ट 2015 में, let  उछाल जाएगा ब्लॉक के शीर्ष पर परिवर्तनीय। हालांकि, परिवर्तनीय घोषणा परिणामों से पहले ब्लॉक में चर को संदर्भित करना ReferenceError (मेरा नोट: अच्छे पुराने की बजाय undefined)। परिवर्तक ब्लॉक की शुरुआत से 'अस्थायी मृत क्षेत्र' में है जब तक कि घोषणा संसाधित न हो जाए। "स्विच स्टेटमेंट्स के लिए भी जाता है क्योंकि केवल एक अंतर्निहित ब्लॉक है" स्रोत: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/... - GitaarLAB


यहां दोनों के बीच अंतर के लिए एक उदाहरण दिया गया है (समर्थन क्रोम के लिए अभी शुरू हुआ): enter image description here

जैसा कि आप देख सकते हैं 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);


39
2017-11-23 22:52



मैं यहाँ क्या उपकरण देख रहा हूँ? - Barton
क्रोम devtools - vlio20
दालचीनी के लिए डेस्कटॉप एप्लेट्स के डेवलपर के रूप में, मुझे ऐसे चमकदार उपकरणों से अवगत नहीं किया गया है। - Barton


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

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

एक funciton के अंदर (लेकिन एक ब्लॉक के बाहर), 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-किट ब्लॉक-स्कॉप्ड है और टीडीजेड है। हालांकि, दो चीजें अलग हैं।

कोई पुनः आवंटन नहीं

परिवर्तनीय घोषित कर दिया 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

38
2018-01-17 15:11





  • परिवर्तनीय नहीं होस्टिंग

    let मर्जी उछाल नहीं ब्लॉक के पूरे दायरे में वे दिखाई देते हैं। इसके विपरीत, var नीचे के रूप में उछाल सकता है।

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

    असल में, प्रति @ बर्गि, दोनों 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 ए के लिए उन नामों के साथ एक नया व्याख्यात्मक वातावरण बनाएं) प्रारंभिक अभिव्यक्ति बी) प्रत्येक पुनरावृत्ति (वृद्धिशील अभिव्यक्ति का मूल्यांकन करने के लिए previosly), अधिक जानकारी हैं यहाँ


20
2018-03-22 14:39



वास्तव में वे अभी भी फहराए गए हैं - Bergi
यिप वे फहराए जाते हैं, लेकिन व्यवहार करते हैं जैसे ड्रम रोल (ड्रम रोल) टेम्पोरल डेड जोन - एक पहचानकर्ता के लिए एक नाटकीय नाम घोषित होने तक पहुंच योग्य नहीं है :-) - Drenai
तो चले गए हैं, लेकिन अनुपलब्ध है? 'फट नहीं' से अलग कैसे है? - N-ate
उम्मीद है कि ब्रायन या बर्गि इसका उत्तर देने के लिए वापस आएंगे। क्या घोषित करने की घोषणा है, लेकिन असाइनमेंट नहीं है? धन्यवाद! - N-ate
@ एन-एट, यहाँ है एक पोस्ट बर्गि, शायद आप इसमें जवाब पा सकते हैं। - zangw


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

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

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

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 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

इसके अलावा यह ईसीएमए 6 फीचर को भी न भूलें, इसलिए यह अभी तक पूरी तरह से समर्थित नहीं है, इसलिए यह बेहतर है कि यह हमेशा बीबीएल इत्यादि का उपयोग कर ईसीएमए 5 पर ट्रांसफर करे ... यात्रा के बारे में अधिक जानकारी के लिए बेबेल वेबसाइट


15
2017-08-18 00:58





दूसरों के पहले से लिखे गए लोगों को जोड़ने के लिए यहां एक उदाहरण दिया गया है। मान लीजिए कि आप कार्यों की एक सरणी बनाना चाहते हैं, 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।


12
2018-05-22 01:09



@aborz: दूसरे उदाहरण में भी बहुत अच्छा अज्ञात फ़ंक्शन सिंटैक्स। यह वही है जो मुझे सी # में उपयोग किया जाता है। मैंने आज कुछ सीखा है। - Barton
सुधार: तकनीकी रूप से, यहां वर्णित तीर फ़ंक्शन सिंटैक्स => developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/... - Barton
दरअसल, आपको जरूरत नहीं है let value = i;। for बयान एक व्याख्यात्मक ब्लॉक बनाता है। - Toothbrush