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


Answers

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

DEMO

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

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

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

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

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

'use strict';

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

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

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




Some hacks with 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"

Getter and setter with 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)



May the following two functions show the difference:

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
}



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

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

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

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

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

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

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

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

    आज, 23 फरवरी 2016, ये कुछ ब्राउज़र हैं जो या तो समर्थन नहीं करते let या केवल आंशिक समर्थन करते हैं:

    • इंटरनेट एक्सप्लोरर 10 और नीचे (कोई समर्थन नहीं)
    • फ़ायरफ़ॉक्स 43 और नीचे (कोई समर्थन नहीं)
    • सफारी 9 और नीचे (कोई समर्थन नहीं)
    • ओपेरा मिनी 8 और नीचे (कोई समर्थन नहीं)
    • एंड्रॉइड ब्राउज़र 4 और नीचे (कोई समर्थन नहीं)
    • ओपेरा 36 और नीचे (आंशिक समर्थन)
    • क्रोम 51 और नीचे (आंशिक समर्थन)

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

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

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

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




var is global scope (hoist-able) variable.

let and const is block scope.

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




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

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

हालांकि यह ध्यान देने योग्य है कि 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 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

एक पाश के अंदर

लूप इन लूप के साथ घोषित वैरिएबल को केवल उस लूप के अंदर संदर्भित किया जा सकता है।

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.

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

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

// 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);
}

अस्थायी मृत क्षेत्र

अस्थायी मृत क्षेत्र की वजह से, घोषित करने से पहले घोषित चर को एक्सेस नहीं किया जा सकता है। ऐसा करने का प्रयास करने से एक त्रुटि फेंकता है।

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

कोई पुन: घोषणा नहीं

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



let is interesting, because it allows us to do something like this:

(() => {
    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++);
            }
        }
    }
})();

Which results in counting [0, 7].

Whereas

(() => {
    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++);
            }
        }
    }
})();

Only counts [0, 1].




This article clearly defines the difference between var, let and const

const is a signal that the identifier won't be reassigned.

let , is a signal that the variable may be reassigned, such as a counter in a loop, or a value swap in an algorithm. It also signals that the variable will be used only in the block it's defined in, which is not always the entire containing function.

var is now the weakest signal available when you define a variable in JavaScript. The variable may or may not be reassigned, and the variable may or may not be used for an entire function, or just for the purpose of a block or loop.

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




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

// 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 दायरा ब्लॉक के पुनरावृत्ति से परे फैला हुआ है जिसमें प्रत्येक फ़ंक्शन बनाया गया था। इसके बजाय, लूप के अंत में, प्रत्येक फ़ंक्शन के बंद होने पर i adderFunctions में प्रत्येक अज्ञात फ़ंक्शन के लिए लूप (1000) के अंत में मूल्य का संदर्भ देता adderFunctions । यह वही नहीं है जो हम चाहते थे: अब हमारे पास बिल्कुल वही व्यवहार के साथ स्मृति में 1000 अलग-अलग फ़ंक्शन हैं। और यदि हम बाद में i मूल्य को अपडेट करते हैं, तो उत्परिवर्तन सभी adderFunctions को प्रभावित करेगा।

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

// 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 लूप के प्रत्येक पुनरावृत्ति पर वापसी करता i । प्रत्येक फ़ंक्शन अब फ़ंक्शन के निर्माण के समय i मान रखता है, और adderFunctions कार्य adderFunctions व्यवहार करता है।

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

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।






Related