ES6- এ কী চলকগুলি বহিষ্কার করা হবে না?


266

আমি কিছুক্ষণ ES6 এর সাথে খেলছি এবং আমি লক্ষ্য করেছি যে ঘোষিত varচলকগুলি প্রত্যাশার মতো উত্তোলন করা হয় ...

console.log(typeof name); // undefined
var name = "John";

... ভেরিয়েবলগুলি ঘোষণার সাথে ঘোষিত letবা constমনে হয় কিছু সমস্যা আছে:

console.log(typeof name); // ReferenceError
let name = "John";

এবং

console.log(typeof name); // ReferenceError
const name = "John";

এর অর্থ কি ভেরিয়েবলগুলি ঘোষিত হয়েছে letবা constউত্তোলন করা হয়নি? সত্যিই এখানে কি ঘটছে না? এই বিষয়ে letএবং এর constমধ্যে কোনও পার্থক্য আছে কি ?

উত্তর:


346

@ থেফোর্তেয়ে এই কথাটি সঠিক যে এই ভেরিয়েবলগুলি ঘোষণার আগে তাদের অ্যাক্সেস করা যায় না । তবে এটি তার চেয়ে কিছুটা জটিল।

ভেরিয়েবলগুলি ঘোষিত হয় letবা তোলা হয় constনা? সত্যিই এখানে কি ঘটছে না?

সকল ঘোষণা ( var, let, const, function, function*, class) "উত্তোলন" হয় জাভাস্ক্রিপ্ট হবে। এর অর্থ হ'ল যদি কোনও স্কোপে কোনও নাম ঘোষণা করা হয় তবে সেই সুযোগে শনাক্তকারী সর্বদা সেই নির্দিষ্ট পরিবর্তনশীলটিকে উল্লেখ করবে:

x = "global";
// function scope:
(function() {
    x; // not "global"

    var/let/… x;
}());
// block scope (not for `var`s):
{
    x; // not "global"

    let/const/… x;
}

এটি ফাংশন এবং ব্লক স্কোপগুলি 1 এর ক্ষেত্রেই সত্য ।

var/ function/ function*ঘোষণাপত্র এবং let/ const/ classঘোষণার মধ্যে পার্থক্য হল আরম্ভ
প্রারম্ভিক undefinedশুরুতে বা (জেনারেটর) ফাংশনটি ডানদিকে যখন বাঁধাই স্কোপের শীর্ষে তৈরি করা হয় ঠিক তখনই করা হয়। আভিধানিক ঘোষিত ভেরিয়েবল তবে থাকার uninitialised । এর অর্থ হল ReferenceErrorআপনি যখন এটি অ্যাক্সেস করার চেষ্টা করবেন তখন একটি ব্যতিক্রম ছুঁড়ে দেওয়া হবে। এটি কেবল তখনই সূচনা হবে যখন let/ const/ classবিবৃতি মূল্যায়ন করা হয়, এর আগে (উপরে) সমস্ত কিছুকে অস্থায়ী মৃত অঞ্চল বলা হয় ।

x = y = "global";
(function() {
    x; // undefined
    y; // Reference error: y is not defined

    var x = "local";
    let y = "local";
}());

লক্ষ্য করুন যে একটি let y;বিবৃতি undefinedপছন্দ মতো চলককে সূচনা করে let y = undefined;

সময়গত মৃত জোন শব্দবিন্যাসের অবস্থান, বরং নয় সময় পরিবর্তনশীল (স্কোপ) তৈরি এবং initialisation মধ্যে। ঘোষণার উপরের কোডটিতে ভেরিয়েবলের রেফারেন্স হিসাবে এটি ত্রুটি নয় যতক্ষণ না সেই কোড কার্যকর করা হয় না (যেমন কোনও ফাংশন বডি বা কেবল ডেড কোড) তবে আপনি যদি আরম্ভের আগে ভেরিয়েবলটি অ্যাক্সেস করেন তবে এটি ব্যতিক্রম হবে কোড ঘোষণার নীচে (যেমন একটি উত্তোলিত ফাংশন ঘোষণায় যা খুব তাড়াতাড়ি বলা হয়)।

এই বিষয়ে letএবং এর constমধ্যে কোনও পার্থক্য আছে কি ?

না, উত্তোলনকে যতটা বিবেচনা করা হয় ততই তারা একই কাজ করে। তাদের মধ্যে পার্থক্যটি হ'ল একটি constপিঁপড়া অবশ্যই হবে এবং কেবলমাত্র ঘোষণার প্রারম্ভিক অংশে নির্ধারিত হতে পারে ( const one = 1;, উভয় const one;এবং পরে পুনরায় নিয়োগগুলি one = 2অবৈধ)।

1: varঘোষণাগুলি অবশ্যই কেবলমাত্র ফাংশন স্তরে কাজ করছে


16
আমি দেখতে পেয়েছি যে সমস্ত ঘোষণাপত্রের মতো let foo = () => bar; let bar = 'bar'; foo();চিত্রগুলি আরও কার্যকরভাবে উত্তোলন করা হয় , কারণ এটি অস্থায়ী মৃত অঞ্চলের কারণে স্পষ্ট নয়।
এস্তাস ফ্লাস্ক

1
আমি লেটের আগে ঘোষিত কোনও কার্যে লেট সংজ্ঞাটি উল্লেখ করার বিষয়ে জিজ্ঞাসা করতে যাচ্ছি (অর্থাত্ একটি বন্ধ)। আমি মনে করি এটি প্রশ্নের উত্তর দেয়, এটি আইনী তবে যদি রেট স্টেটমেন্ট কার্যকর হওয়ার আগে ফাংশনটি চালিত হয় তবে এটি একটি ত্রুটিযুক্ত ত্রুটি হবে এবং পরে যদি ফাংশনটি আহ্বান করা হয় তবে তা ঠিক হয়ে যাবে। সত্য উত্তর হলে সম্ভবত এই উত্তর যুক্ত করা যেতে পারে?
মাইক লিপার্ট

2
@ মাইকলিপার্ট হ্যাঁ, এটি সঠিক। ভেরিয়েবলটি আরম্ভ করার আগে আপনাকে যে ফাংশনটি অ্যাক্সেস করে তা আপনাকে কল করতে হবে না। উদাহরণস্বরূপ, প্রতিটি উত্তোলিত ফাংশন ঘোষণার সাথে এই দৃশ্যটি দেখা দেয়।
বার্গি

1
constমত করার সিদ্ধান্তটি letএকটি ডিজাইনের ত্রুটি। একটি সুযোগের মধ্যে, constউত্তোলন করা উচিত ছিল এবং যখন এটি অ্যাক্সেস করা হয় তখন কেবল ইন-টাইম-ইনিশিয়াল করা উচিত। সত্যই, তাদের একটি const, ক letএবং অন্য কীওয়ার্ড থাকা উচিত যা একটি ভেরিয়েবল তৈরি করে যা "পঠনযোগ্য" এর মতো কাজ করে let
পেসারিয়ার

1
" প্রাক্তনদের অপরিবর্তিত দিয়ে শুরু করা হয় ..." ভের ঘোষণার জন্য ঠিক হতে পারে তবে ফাংশন ঘোষণার জন্য এটি যথাযথ বলে মনে হয় না, যা কার্যকরকরণ শুরুর আগে একটি মান নির্ধারিত হয়।
রবজি

87

ECMAScript 6 (ECMAScript 2015) স্পেসিফিকেশন letএবং constঘোষণা বিভাগের উদ্ধৃতি ,

ভেরিয়েবলগুলি তৈরি করা হয় যখন তাদের লেক্সিকাল এনভায়রনমেন্ট ইনস্ট্যান্ট করা থাকে তবে ভেরিয়েবলের লেক্সিকাল বাইন্ডিংয়ের মূল্যায়ন না করা পর্যন্ত কোনওভাবেই অ্যাক্সেস করা যাবে না

সুতরাং, আপনার প্রশ্নের উত্তর দিতে, হ্যাঁ, letএবং constউত্তোলন করুন তবে রানটাইমের সময় আসল ঘোষণার মূল্যায়ন করার আগে আপনি এগুলি অ্যাক্সেস করতে পারবেন না।


22

ES6Letভেরিয়েবলের সাথে পরিচয় হয় যা সামনে আসে block level scoping। যতক্ষণ না ES5আমাদের উপস্থিত ছিল block level scoping, সুতরাং যে ব্লকগুলির মধ্যে ঘোষিত ভেরিয়েবলগুলি সর্বদা hoistedস্তরের স্কোপিংয়ের কাজ করে।

মূলত Scopeআপনার প্রোগ্রামে কোথায় আপনার ভেরিয়েবলগুলি দৃশ্যমান তা নির্দেশ করে যা আপনাকে ঘোষিত ভেরিয়েবলগুলি কোথায় ব্যবহার করার অনুমতি দেয় তা নির্ধারণ করে। ইন ES5আছে global scope,function scope and try/catch scope, সঙ্গে ES6আমরা ব্লক স্তর scoping আসুন ব্যবহার করে পেতে।

  • আপনি varকীওয়ার্ডের সাথে কোনও ভেরিয়েবল সংজ্ঞায়িত করার সময় এটি নির্ধারিত মুহুর্ত থেকে পুরো ফাংশনটি জানতে পারে।
  • আপনি যখন letবিবৃতি সহ কোনও ভেরিয়েবল সংজ্ঞায়িত করেন তবে এটির সংজ্ঞাটি কেবলমাত্র ব্লকটিতেই তা জানা যায়।

     function doSomething(arr){
         //i is known here but undefined
         //j is not known here
    
         console.log(i);
         console.log(j);
    
         for(var i=0; i<arr.length; i++){
             //i is known here
         }
    
         //i is known here
         //j is not known here
    
         console.log(i);
         console.log(j);
    
         for(let j=0; j<arr.length; j++){
             //j is known here
         }
    
         //i is known here
         //j is not known here
    
         console.log(i);
         console.log(j);
     }
    
     doSomething(["Thalaivar", "Vinoth", "Kabali", "Dinesh"]);

আপনি যদি কোডটি চালান, আপনি দেখতে পেলেন যে ভেরিয়েবলটি jকেবল loopআগে এবং পরে নয় কেবল পরিচিত । তবুও, আমাদের ভেরিয়েবলটি iপরিচিত হয়entire function পরে সংজ্ঞায়িত হওয়ার মুহুর্ত থেকেই এটি ।

লেট ব্যবহার করে আরও একটি দুর্দান্ত সুবিধা রয়েছে যেহেতু এটি একটি নতুন লেজিকাল পরিবেশ তৈরি করে এবং একটি পুরানো রেফারেন্স রাখার পরিবর্তে তাজা মানকে বাঁধে।

for(var i=1; i<6; i++){
   setTimeout(function(){
      console.log(i);
   },1000)
}

for(let i=1; i<6; i++){
   setTimeout(function(){
      console.log(i);
   },1000)
}

প্রথম forলুপ সর্বদা সর্বশেষ মানটি মুদ্রণ করে , letএটি একটি নতুন সুযোগ তৈরি করে এবং আমাদের মুদ্রণ করে নতুন মানগুলিকে আবদ্ধ করে 1, 2, 3, 4, 5

আসার জন্য constants, এটি মূলত এর মতো কাজ করে let, কেবলমাত্র পার্থক্য হ'ল তাদের মান পরিবর্তন করা যায় না। ধ্রুবকগুলিতে রূপান্তর অনুমোদিত তবে পুনরায় নিয়োগের অনুমতি নেই।

const foo = {};
foo.bar = 42;
console.log(foo.bar); //works

const name = []
name.push("Vinoth");
console.log(name); //works

const age = 100;
age = 20; //Throws Uncaught TypeError: Assignment to constant variable.

console.log(age);

যদি একটি ধ্রুবক একটিকে বোঝায় তবে objectএটি সর্বদা উল্লেখ করে objectতবে objectনিজেই পরিবর্তন করা যায় (যদি এটি পরিবর্তনীয় হয়)। আপনি যদি অপরিবর্তনীয় objectথাকতে চান তবে আপনি এটি ব্যবহার করতে পারেনObject.freeze([])


5

থেকে MDN ওয়েব দস্তাবেজ:

ECMAScript 2015 এ, letএবং constউত্তোলন করা হয়েছে তবে আরম্ভ করা হয়নি। ভেরিয়েবলের ঘোষণার আগে ব্লকের ভেরিয়েবল উল্লেখ করে ReferenceErrorকারণ ভেরিয়েবলটি ব্লক শুরু হতে "অস্থায়ী ডেড জোনে" থাকে যতক্ষণ না ডিক্লেয়ারেশন প্রক্রিয়া হয়।

console.log(x); // ReferenceError
let x = 3;

0

এস in এ যখন আমরা লেট বা কনস্ট ব্যবহার করি তখন সেগুলি ব্যবহারের আগে আমাদের ভেরিয়েবলটি ঘোষণা করতে হয়। যেমন। 1 -

// this will work
u = 10;
var u;

// this will give an error 
k = 10;
let k;  // ReferenceError: Cannot access 'k' before initialization.

যেমন। 2-

// this code works as variable j is declared before it is used.
function doSmth() {
j = 9;
}
let j;
doSmth();
console.log(j); // 9
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.