let در جاوا اسکریپت: شناسایی متغیرهای Block-Scoped

خلاصه: در این آموزش، چگونگی استفاده از کلمه کلیدی let در جاوا اسکریپت برای شناسایی متغیرهای Block-Scoped را می آموزید.

مقدمه ای بر کلمه کلیدی let در جاوا اسکریپت

در ES5، وقتی با استفاده از کلمه کلیدی var یک متغیر را شناسایی می کنید، scope  متغیر یک متغیر سراسری است اگر آن را خارج از تابع مشخص کنید و درصورتی که داخل تابع مشخص شود یک function- scoped نامیده می شود.

let variable_name = value;

مثال زیر را مشاهده کنید:

let x = 10;
if (x == 10) {
    let x = 20;
    console.log(x); // 20;
}
console.log(x); // 10

اجازه دهید چگونگی عملکرد این دستورالعمل را توضیح دهیم:

-ابتدا یک متغیر x را مشخص کرده و مقدار ۱۰ را به آن اختصاص می دهیم.

-مرحله دوم، متغیری جدید با همان نام x در بلوک if مشخص می کنیم، با ارزش اولیه ۲۰.

-در مرحله سوم، مقدار x را داخل و بعد از بلوک if خارج می کنیم.

چون کلمه کلیدی let یک متغیر Block-Scoped مشخص می کند، متغیر x داخل بلوک if یک متغیر جدید است و متغیر x مشخص شده را بالای دستورالعمل پنهان می کند. بنابراین مقدار x در console برابر است با ۲۰.

وقتی جاوا اسکریپت اجرای بلوک if را کامل می کند، متغیر x داخل بلوک if بیرون از scope است. بنابراین مقدار متغیر x که بلوک if را دنبال می کند برابر است با ۱۰.

let جاوا اسکریپت و شیء سراسری

وقتی یک متغیر را با استفاده از کلمه کلیدی var مشخص می کنید، آن متغیر را به لیست ویژگی های شی سراسری اضافه می کنید. در مورد مرورگرهای وب شی سراسری window است.

به مثال زیر توجه کنید:

var a = 10;
console.log(window.a); // 10

اما، وقتی از کلمه کلیدی let برای مشخص کردن یک ‌متغیر استفاده می کنید، متغیر به عنوان یک ‌ویژگی به شی سراسری نپیوسته است. به مثال زیر دقت کنید:

let b = 20;
console.log(window.b); // undefined

let جاوا اسکریپت و متغیر callback در یک  for loop

مثال زیر را مشاهده کنید:

for (var i = 0; i < 5; i++) {
    setTimeout(function () {
        console.log(i);
    }, ۱۰۰۰);
}

منظور این کد خارج کردن اعداد از صفر تا ۴ در console در هر ثانیه است. اما عدد ۵ را پنج بار خارج می کند.

دلیل این عمل این است که بعد از پنج بار تکرار، مقدار متغیر i عدد ۵ است و پنج مورد از تابع callback به تابع setTimeOut() منتقل شده به همان متغیر i با مقدار نهایی ۵ اعمال می شود.

در ES5 این موضوع را با ایجاد یک scope دیگر ثابت می کند بطوریکه هر نمونه تابع callback در یک ‌متغیر جدید اعمال می شود و برای ایجاد یک scope جدید، به ایجاد یک تابع نیاز دارد.

برای نمونه از الگوی IIFE مانند مثال زیر استفاده کنید:

for (var i = 0; i < 5; i++) {
    (function (j) {
        setTimeout(function () {
            console.log(j);
        }, ۱۰۰۰);
    })(i);
}

در ES6 کلمه کلیدی let یک متغیر جدید در هر نمونه loop مشخص می کند، بنابراین برای حل این موضوع فقط باید کلمه کلیدی var را با کلمه کلیدی let جابه جا کنید.

for (let i = 0; i < 5; i++) {
    setTimeout(function () {
        console.log(j);
    }, ۱۰۰۰);
}

برای ساخت کدی با مدل ES6 می توانید از تابع arrow مانند مثال زیر استفاده کنید:

for (let i = 0; i < 5; i++) {
    setTimeout(() => console.log(i), 1000);
}

متغیرهای let جاوا اسکریپت و hoisting

بیایید مثال زیر را امتحان کنیم:

(function () {
    console.log(foo); // ReferenceError: foo is not defined
    let foo = 'function scope';
}());

در تابع، به دلیل خطای مرجع، به متغیر foo قبل از شناسایی آن دسترسی پیدا می کنیم.به نظر می رسد شناسایی یک متغیر با استفاده از کلمه کلیدی let عملی نباشد، اما هست.

درواقع، موتور جاوا اسکریپت شناسایی متغیرها را با استفاده از کلمه کلیدی let تا بالای بلوک عملی می کند. اما اگر یک متغیر را قبل از شناسایی به بلوک بازگردانید یک خطای مرجع دریافت خواهید کرد

Temporal death zone (TDZ)

متغیر A که توسط کلمه کلیدی let شنایایی شود، به اصطلاح دارای یک TDZ است. TDZ  شامل  مدت زمانی است از شروع بلوک تا وقتی که شناسایی متغیر به نتیجه برسد.

مثال زیر نشان می دهد که TDZ مبتنی بر زمان است نه مبتنی بر مکان:

{ // enter new scope, TDZ starts
    let log = function () {
        console.log(foo); // foo declared later
    };
 
    // This is the TDZ and accessing foo 
    // would cause a ReferenceError
 
    let foo = 10; // TDZ ends
    log(); // called outside TDZ
}

ابتدا، وقتی کروشه یک scope جدید شروع کند، TDZ شروع می شود.

سپس، تابع log دسترسی به متغیر foo را نمایش می دهد. اما، تابع log() هنوز اجرا نشده، پس درست است.

سپس متغیر foo را تعریف کرده و بین صفر تا ۱۰ ارزش گذاری می کنیم. مدت زمانی از شروع scope به اتصال که متغیر foo شناسایی می شود را TDZ می نامند.

وقتی موتور جاوااسکریپت شناسایی را پردازش کرد، TDZ به پایان می رسد.

بعد از آن، تابع log() که به متغیر foo خارج از TDZ دسترسی دارد را فرا می خوانیم.

توجه داشته باشید که اگر در TDZ به یک متغیر شناسایی شده توسط کلمه کلیدی let دسترسی داشته باشید، خطای مرجع دریافت می کنید، مانند نمونه زیر:

{ // TDZ starts
    console.log(typeof bar); // undefined
    console.log(typeof foo); // ReferenceError
    let foo; // TDZ ends
}

نکته: متغیر bar یک ‌متغیر ناموجود است، پس نوع آن تعریف نشده.

نکته آخر اینکه برای ES6 پیشنهاد شده که باید کلمه کلیدی let را سازگار کنید و استفاده از کلمه کلیدی var را هنگام شناسایی یک متغیر، متوقف کنید.

1 Star2 Stars3 Stars4 Stars5 Stars (1 votes, average: 5٫00 out of 5)
Loading...

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

counter customizable free hit