برسی متغیرهای var در جاوااسکریپت

در این مقاله قصد داریم تا تعریف متغیر با کلمه کلیدی var را زیر ذره بین ببریم و کمی درمورد اون صحبت کنیم، پس در این مقاله باما همراه باشید.

کلمه var یک متغیر function-scoped یا globaly-scoped تعریف میکنه و ما موقع تعریف کردن یک متغیر با کلمه کلیدی var مختار هستیم تا در همان ابتدا برای اون یک value ( مقدار ) در نظر بگیریم.

var x = 1;

if (x === 1) {
  var x = 2;

  console.log(x);
  // خروجی موردانتظار: 2
}

console.log(x);
// خروجی موردانتظار: 2

سینتکس تعریف متغیر با کلمه var

// کلمه value1 و value2 میتونن هرچیزی باشن، مثل string, number, boolean, array, object

var name1;
var name1 = value1;
var name1 = value1, name2 = value2;
var name1, name2 = value2;
var name1 = value1, name2, /* …, */ nameN = valueN;

همچنین امکان Destructuring هم برای متغیرهایی که مقدارشون برابر با یک object هست هم وجود داره، مثل نمونه زیر:

var foo = {
  bar:10,
  baz:12,
}

var { bar } = foo; // where foo = { bar:10, baz:12 };
/* بااینکار درواقع ما داریم یک متغیر دیگه به نام bar میسازیم که مقدارش برابر با 10 هستش */

متغیرهایی که با کلمه var تعریف میشوند، فارغ از محل تعریف شدنشون،قبل از هر کدی پردازش خواهند شد، اینرو اصطلاحا hoisting مینامیم و در ادامه کمی بیشتر درموردش صحبت خواهیم کرد.

scope متغیرهایی که با var تعریف میشوند همان زمینه اجرای فعلی اونهاست یعنی اگر متغیری رو داخل یک function تعریف کنیم، scope اون متغیر محدود به همان function خواهد بود اما اگر خارج از هرگونه function یک متغیر با کلمه var تعریف کنیم، scope اون global میشه و در سرتاسر زمینه اجرا یا سند مربوطه در دسترس هستند. همچنین با تعریف تکراری یک متغیر هم با ارور مواجه نخواهیم شد و هم اون متغیر value خودش رو از دست نخواهد داد، حتی در حالت strict mode و فقط زمانی تعریف تکراری متغیرها باعث ایجاد ارور میشن که به اون متغیر یک مقدار جدیدی را منصوب کنیم.

البته به این نکته توجه داشته باشید که scope متغیرهای top-level در Nodejs Commonjs و ECMAScript همان ماژول مربوطه هست و scope اونها global نخواهد بود.

function foo() {
  var x = 1;
  function bar() {
    var y = 2;
    console.log(x); 
    console.log(y); // 2 (`y` داخل scope هست)
  }
  bar();
  console.log(x); // 1 (`x` داخل scope هست)
  console.log(y); // ReferenceError, `y` در اینجا بهش دسترسی نداریم
}

foo();

var hoisting

همانطور که قبلتر گفتیم، متغیرهایی که با کلمه var تعریف میشوند، فارغ از محل تعریف شدنشون،قبل از هر کدی پردازش خواهند شد و به بالای scope خودشون خواهند رفت و این به آن معناست که میتوان به این متغیرها قبل از محل تعریف شدنشون هم دسترسی داشت و به این رفتار اصطلاحا hoisting میگوییم.

به این خاطر بهتر هست که همیشه متغیرهای خودتون رو در بالاترین نقطه scope مدنظرتون ( که حال یا function هست یا global scope ) تعریف کنید. و این نکته راهم به خاطر داشته باشید که فقط variable declaration ( تعریف خود متغیر ) hoist و به بالای scope منتقل میشن و مقدار اونها قبل از منصوب شدن مقداری، برابر با undefined خواهد بود.

function do_something() {
  console.log(bar); // undefined
  var bar = 111;
  console.log(bar); // 111
}

چند مثال مختلف از تعریف متغیر با کلمه var

تعریف و مقداردهی 2 متغیر

var a = 0,
  b = 0;

مقداردهی 2 متغیر با یک مقدار string

var a = &quotA&quot
var b = a;

کد بالا برابره با مثال زیر:

var a, b = a = 'A';

همچنین حواستون به نظم تعریف کردن متغیرها باشه تا مثل نمونه زیر با مقدار undefined مواجه نشید:

var x = y,
  y = &quotA&quot
console.log(x + y); // undefinedA

در اینجا x و y قبل از اینکه توی چرخه کد اجرا بشن تعریف شدن و درنتیجه ReferenceError دریافت نخواهیم کرد اما مقدار دهی اونها چند خط بعد انجام شده و مقدار x در اینجا برابر با undefined هست و چندخط بعد مقدار y برابر با "A" قرار میگیره و درنتیجه هنگام جمع x و y ما خروجی undefinedA را مشاهده میکنیم.

مقداردهی  اولیه چند متغیر

var x = 0;
function f() {
  var x = y = 1; // x locally و y globally.
}
f();

console.log(x, y); // 0 1

// درحالت بدون استفاده از strict-mode:
// x طبق انتظارمون global هست;
// y هم خارج از فانکشن ما به بیرون scope خودش درز کرده!

همین مثال بالا اما اینبار در حالت strict-mode:

&quotuse strict&quot

var x = 0;
function f() {
  var x = y = 1; // ReferenceError در strict mode.
}
f();

console.log(x, y);


منبع: کلمه var در جاوااسکریپت چیست - وسپار