کلیدواژه ی let در ECMAScript 2015

05 اسفند 1397
javascript-let-var

با سلام خدمت شما خوانندگان گرامی، در سال 2015 دو کلیدواژه ی مهم به نام های let و const به جاوا اسکریپت معرفی شد که کارشان تعریف Block Scope در متغیرها بود. قبل از ECMAScript 2015 تنها دو نوع scope در جاوا اسکریپت داشتیم: Global Scope و Function Scope. امروز قصد داریم در رابطه با اولین مورد، یعنی let، صحبت کنیم. ابتدا باید نگاهی به این دو scope اولیه داشته باشیم...

Global Scope

متغیرهایی که به صورت سراسری یا Global (به عبارتی خارج از توابع) تعریف شوند، دارای Global scope یا دامنه ی سراسری هستند:

<!DOCTYPE html>
<html>
<body>

<h2>JavaScript Scope</h2>

<p>A GLOBAL variable can be accessed from any script or function.</p>

<p id="demo"></p>

<script>
var carName = "Volvo";
myFunction();

function myFunction() {
  document.getElementById("demo").innerHTML = "I can display " + carName;
}
</script>

</body>
</html>

خروجی این کد عبارت "I can display Volvo" خواهد بود.

ما می توانیم از هر جایی که بخواهیم به متغیر های سراسری یا Global دسترسی پیدا کنیم.

Function Scope

توابعی که به صورت محلی (Local) تعریف شوند (به عبارتی داخل تابع باشند) دارای Function Scope هستند:

<!DOCTYPE html>
<html>
<body>

<h2>JavaScript Scope</h2>

<p>Outside myFunction() carName is undefined.</p>

<p id="demo1"></p>

<p id="demo2"></p>

<script>
myFunction();

function myFunction() {
  var carName = "Volvo";
  document.getElementById("demo1").innerHTML = typeof carName + " " + carName;
}
document.getElementById("demo2").innerHTML = typeof carName;
</script>

</body>
</html>

خروجی این تابع به این صورت خواهد بود:

string Volvo

undefined

متغیر های محلی تنها از داخل خودِ تابع در دسترس هستند و همانطور که در مثال بالا می بینید اگر آن ها را از بیرون تابع صدا بزنیم به مقدار undefined برمیخوریم.

Block Scope

تا اینجا متوجه شدیم که اگر متغیری با var تعریف شود نمی تواند Block Scope داشته باشد. حال متغیر هایی که داخل بلوکه ای تعریف شوند (یعنی داخل علامت های { } باشند) از بیرون هم قابل دسترسی هستند. مثال:

{ 
  var x = 2; 
}
// باز هم می توان از اینجا به ایکس دسترسی داشت

قبل از ES2015 چنین چیزی (Block Scope به معنی دامنه ی بلوکه ای) در جاوا اسکریپت وجود نداشت اما متغیرهایی که با استفاده از let تعریف شوند دارای Block Scope هستند بنابراین اگر داخل بلوکه { } تعریف شوند، دیگر از خارج قابل دسترسی نیستند:

{ 
  let x = 2;
}
// دیگر از اینجا نمی شود به ایکس دسترسی داشت چرا که دامنه ی خاصی دارد

در مثال بالا scope داریم و به همین علت تنها داخل آن scope می توانیم از آن استفاده کنیم.

تعریف دوباره ی متغیرها

اگر متغیر ها را با استفاده از var تعریف کنیم و بخواهیم دوباره آن را تعریف کنیم به مشکل برمیخوریم. به مثال زیر دقت کنید:

<!DOCTYPE html>
<html>
<body>

<h2>Declaring a Variable Using var</h2>

<p id="demo"></p>

<script>
var  x = 10;
// مقدار ایکس در اینجا 10 است
{  
  var x = 2;
  // مقدار ایکس در اینجا 2 است
}
// مقدار ایکس در اینجا 2 است
document.getElementById("demo").innerHTML = x;
</script>

</body>
</html>

خروجی این کد عدد 2 خواهد بود.

احتمالا متوجه مشکل شده اید؛ از آنجا که var ها scope بلوکه ای ایجاد نمی کنند، اگر متغیر را در بلوکی دوباره declare کنید از آن به بعد مقدارش تغییر می کند. راه حل چیست؟

شما می توانید از let استفاده کنید تا متغیرهایتان دارای scope شوند:

<!DOCTYPE html>
<html>
<body>

<h2>Declaring a Variable Using let</h2>

<p id="demo"></p>

<script>
var  x = 10;
// مقدار ایکس در اینجا 10 است
{  
  let x = 2;
  // مقدار ایکس در اینجا 2 است
}
// مقدار ایکس در اینجا 10 است
document.getElementById("demo").innerHTML = x;
</script>

</body>
</html>

خروجی این کد عدد 10 می باشد.

پشتیبانی از کلیدواژه ی let به شرح زیر است:

Opera 36 Safari 11 Firefox 44 IE / Edge 12 Chrome 49
Mar, 2016 Sep, 2017 Jan, 2015 Jul, 2015 Mar, 2016

نسخه هایی که در جدول بالا آمده است، اولین نسخه ای است که از کلیدواژه ی let پشتیبانی می کند بنابراین Internet Explorer 11 از آن پشتیبانی نمی کند.

Loop Scope

اگر در یک حلقه از var استفاده کنید:

var i = 5;
for (var i = 0; i < 10; i++) {
  // some statements
}
// 10 است i مقدار

اگر از let استفاده کنید:

let i = 5;
for (let i = 0; i < 10; i++) {
  // some statements
}
// 5 است i مقدار

توضیح:

  • در مثال اول از var استفاده کردیم بنابراین متغیری که داخل تابع تعریف کرده ایم دوباره خارج از تابع تعریف می شود.
  • در مثال دوم از let استفاده کرده ایم بنابراین متغیری که داخل تابع تعریف شده است دوباره خارج است تابع تعریف نمی شود.

Function Scope و Global Scope

استفاده از var یا let داخل توابع هیچ تغییری ایجاد نمی کند و همچنان Function Scope برقرار خواهد بود. دو کد زیر از نظر scope هیچ تفاوتی با هم ندارند:

function myFunction() {
  var carName = "Volvo";   // Function Scope
}
function myFunction() {
  let carName = "Volvo";   // Function Scope
}

این نکته برای Global Scope نیز صادق است و دو کد زیر یک Scope را دارند:

var x = 2;       // Global scope
let x = 2;       // Global scope

متغیر های سراسری در HTML

همانطور که می دانید scope سراسری یا global در جاوا اسکریپت، همان محیط اجرای جاوا اسکریپت است که در HTML می شود همان شیء window. بنابراین متغیرهای سراسری که با var تعریف شوند جزئی از شیء window خواهند بود. به طور مثال هر دو کد زیر یکسان هستند:

var carName = "Volvo";


document.getElementById("demo").innerHTML = "I can display " + carName;
var carName = "Volvo";


document.getElementById("demo").innerHTML = "I can display " + window.carName;

خروجی هر دو کد عبارت "I can display Volvo" خواهد بود.

قوانین تعریف کردن چندباره ی متغیر ها

قانون اول: اجازه دارید متغیر هایی را که با var تعریف شده اند، در هر کجا از برنامه تان دوباره declare یا تعریف کنید:

var x = 2;
var x = 3;

قانون دوم: تعریف دوباره ی متغیر های var با کلیدواژه ی let (اگر در یک scope باشند) مجاز نیست و تنها اولی محاسبه می شود:

var x = 2;       // مجاز
let x = 3;       // غیر مجاز

همچنین تعریف دوباره ی متغیر های let  با let در یک scope مجاز نمی باشد:

let x = 2;       // مجاز
let x = 3;       // غیر مجاز

اما اگر در scope دیگر باشند، مشکلی نیست:

let x = 2;       // مجاز

{
  let x = 3;   // مجاز
}

این قانون برای جایگزینی متغیر های let با var نیز صادق است.

مبحث Hoisting

در جلسات قبلی در رابطه با مبحث Hoisting صحبت کرده ایم. متغیر هایی که با var تعریف شوند Hoist می شوند اما متغیر های let سر جایشان باقی می مانند و Hoist نمی شوند. بنابراین اگر قبل از تعریف متغیر های let، از آن ها استفاده کنید با خطای ReferenceError مواجه می شوید.

امیدوارم از این قسمت لذت برده باشید. در قسمت بعد به سراغ مبحث const خواهیم رفت.

تمام فصل‌های سری ترتیبی که روکسو برای مطالعه‌ی دروس سری آموزش جاوا اسکریپت | Javascript توصیه می‌کند:
نویسنده شوید
دیدگاه‌های شما (3 دیدگاه)

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.

امیرحسین
25 اردیبهشت 1400
ممنون از سایت خوبتون به بهترین شکل توضیح دادین مرسی

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.

yac
03 مرداد 1398
fkr nakonam bishtar azin mishod pichondesh

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.

امیر زوارمی
05 مرداد 1398
سلام دوست عزیز بنده سعی کردم در ساده ترین حالت توضیح بدم اما نکات فنی رو جا نزارم. اگر کوتاهی بوده عذرخواهی می کنم. در ضمن در قسمت کامنت ها میشه سوالات رو پرسید تا مطلب واضح تر بشه براتون.

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.

مسعود
23 اردیبهشت 1398
با سلام و خسته نباشید بابت آموزش های خوبتون در مورد تعریف دو متغیر هم نام در یک اسکوپ به روش زیر var x = 2; // مجاز let x = 3; // غیر مجاز تست کردم اما برعکس گفته شما هر دو متغییر غیر مجاز هستند، لطفا بررسی شود کد تست شده که خروجی نداشت: JavaScript Scope Outside myFunction() carName is undefined. var x = 2; // مجاز let x = 3; // غیر مجاز document.getElementById("demo2").innerHTML = x;

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.

امیر زوارمی
23 اردیبهشت 1398
سلام دوست عزیز... چند نکته در این مورد هست: 1- باید یکی از متغیر ها درون براکت (علامت {}) باشند نه هر دو در یک قسمت... کد بالا را نگاه کنید. آن را به این شکل نوشته ایم: var x = 10; // مقدار ایکس در اینجا 10 است { let x = 2; // مقدار ایکس در اینجا 2 است } 2- مرورگر شما باید به روز باشد تا از let پشتیبانی کند. جدول پشتیبانی مرورگر ها را برایتان قرار داده ایم. 3- از طرفی اگر از دستور زیر بدون ایجاد عنصر demo در HTML استفاده کنید با خطا مواجه می شوید: document.getElementById("demo").innerHTML = x; دلیل آن هم واضح است؛ هیچ عنصر demo ای وجود ندارد که محتوای x را در آن قرار دهیم. (مراقب باشید اگر id کد شما در HTML مقدار demo در جاوا اسکریپت هم demo و اگر چیز دیگری مانند Demo2 است در جاوا اسکریپت هم demo2 قرار داده شود. 4- اما اگر منظورتان کد زیر است: var x = 2; // مجاز let x = 3; // غیر مجاز منظور ما این نبوده است که در این حالت اولی مجاز خواهد بود. اینجا منظور ما این است که اولی مجاز است (به خودی خود) تا زمانی که دومی اضافه شود. زمانی که دومی اضافه شود کلا غیر مجاز خواهند بود. کامنت هایی که مجاز یا غیر مجاز بودن را نوشته اند منظورشان کل «روند اجرای برنامه ی جاوا اسکریپت» به صورت خط به خط است و اشاره به خود متغیر ندارند.

در این قسمت، به پرسش‌های تخصصی شما درباره‌ی محتوای مقاله پاسخ داده نمی‌شود. سوالات خود را اینجا بپرسید.