var في JavaScript

من موسوعة حسوب
اذهب إلى: تصفح، ابحث

تعبير variable يُصرِّح عن متغير، ويمكن تهيئة قيمته الابتدائية اختياريًا.

البنية العامة

var varname1 [= value1] [, varname2 [= value2] ... [, varnameN [= valueN]]];

varnameN

اسم المتغير، ويمكن أن يكون أيّ معرِّف صالح في JavaScript.

valueN

القيمة الابتدائية للمتغير، ويمكن استخدام أيّ تعبير (expression) صالح في JavaScript، والقيمة الافتراضية هي undefined.

الوصف

التصريح عن المتغيرات سيُعالَج قبل تنفيذ أيّة شيفرات أينما وقعت، ومجال (scope) المتغيرات المُصرَّح عنا عبر var هو سياق التنفيذ الحالي (execution context)، كمجال الدوال، أو المجال العام (إن صُرِّحَ عن المتغيرات خارج أيّة دالة). لاحظ أنَّ إعادة التصريح عن المتغيرات في JavaScript لا تفقدها قيمتها.

إسناد قيمة إلى متغيّر غير مصرَّح عنه سيؤدي إلى إنشاء متغير عام (أي أنَّه سيصبح خاصية [property] للكائن العام [global object])؛ الاختلافات بين المتغيرات المُصرَّح عنها والمتغيرات غير المُصرَّح عنها هي:

1. المتغيرات المُصرَّح عنها سيتكون محدودةً في سياق التنفيذ الذي عُرِّفَت فيه، أما المتغيرات غير المُصرَّح عنها ستكون عامّةً دومًا.
function x() {
  y = 1;   // سترمي الاستثناء ReferenceError في وضع strict
  var z = 2;
}

x();

console.log(y); // "1" 
console.log(z); // سترمي الاستثناء ReferenceError: z is not defined outside x
2. المتغيرات المُصرَّح عنها ستُنشَأ قبل تنفيذ أيّة شيفرات، بينما المتغيرات غير المُصرَّح عنها فلن تكون موجودةً حتى تُنفَّذ الشيفرة التي تُنشِئها:
console.log(a);                // رمي الاستثناء ReferenceError.
console.log('still going...'); // لن يُنفَّذ هذا التعبير
أما المتغيرات المُصرَّح عنها:
var a;
console.log(a);                // "undefined" أو ""
console.log('still going...'); // "still going..."
3. المتغيرات المُصرَّح عنها ستكون خاصيةً (property) غير قابلة للضبط في سياق التنفيذ (الدالة أو الكائن العام)، بينما المتغيرات المُصرَّح عنها يمكن ضبطها (configurable) (أي يمكن حذفها على سبيل المثال):
var a = 1;
b = 2;

 // رمي الاستثناء TypeError في وضع strict
// أو سيفشل التنفيذ بصمت عدا ذلك
delete this.a;

delete this.b;

console.log(a, b); // رمي الاستثناء ReferenceError. 
// إذ حُذِفَت الخاصية ولم تعد موجودةً
بسبب الاختلافات الثلاثة السابقة، نجد أنَّ عدم التصريح عن المتغيرات يؤدي في أغلب الأحيان إلى نتائج غير متوقعة؛ لذا من المستحسن التصريح عن المتغيرات دومًا سواءً كانت ضمن مجال إحدى الدوال أو في المجال العام؛ لاحظ أنَّ إسناد قيمة إلى متغير غير مُصرَّح عنه في ECMAScript 5 مع تفعيل النمط strict سيؤدي إلى رمي خطأ.

استخدام المتغيرات قبل تعريفها

لمّا كان التصريح عن المتغيرات سيُعالَج قبل تنفيذ أيّة شيفرات، فالتصريح عن المتغير في أيّ مكان في الشيفرة سيكافئ التصريح عنها في بداية الملف، وهذا يعني أنَّه يمكن استخدام المتغير قبل التصريح عنه:
bla = 2;
var bla;
// ...

// ستُفسَّر الشيفرة السابقة كما يلي

var bla;
bla = 2;
ولهذا السبب من المستحسن التصريح عن المتغيرات في أعلى المجال الذي تتبع إليه (أي أعلى الشيفرة للمتغيرات في المجال العام، أو أعلى الدالة) لكي يكون واضحًا ما هي المتغيرات التي سنحصل عليها من مجال الدالة (function scope، أي أنها متغيرات محليّة) وما هي المتغيرات التي سنستبين قيمتها عبر سلسلة المجال (scope chain). من المهم الإشارة إلى أنَّ هذا السلوك سيؤثر على التصريح عن قيمة المتغير وليس له أثر على تهيئة قيمته، أي أنَّ القيمة ستُسنَد إلى المتغير عند وصول التنفيذ إليها:
function do_something() {
  console.log(bar); // undefined
  var bar = 111;
  console.log(bar); // 111
}

// ستُفسَّر الشيفرة السابقة كما يلي 
function do_something() {
  var bar;
  console.log(bar); // undefined
  bar = 111;
  console.log(bar); // 111
}

أمثلة

التصريح عن متغيرين وتهيئة قيمتهما

var a = 0, b = 0;

التصريح عن متغيرين لهما نفس القيمة النصية

var a = 'A';
var b = a;

// ما سبق يكافئ

var a, b = a = 'A';
لكن ضع ببالك أنَّ عليك استخدام الترتيب الصحيح:
var x = y, y = 'A';
console.log(x + y); // undefinedA
صرحنا هنا عن المتغيرين x و y قبل تنفيذ الشيفرة، وبدأت عملية الإسناد من التعبير x = y وكان المتغير y موجودًا لذا لم يُرمَ الاستثناء ReferenceError وكانت القيمة المعادة هي undefined، لذا أصبحت قيمة x تساوي undefined، ثم أُسندت القيمة A إلى المتغير y؛ وبالتالي أصبح x === undefined && y === 'A'‎.

تهيئة عدِّة متغيرات

var x = 0;

function f() {
  var x = y = 1;
}
f();

console.log(x, y);
لاحظ أنَّ المتغير x قد عُرِّف محليًا داخل الدالة f()‎ لكن المتغير y لم يكن محليًا؛ وعند محاولة الوصول إلى قيمة المتغيرين خارج الدالة فسيُرمى الاستثناء ReferenceError في النمط strict (لأن المتغير y غير مُعرَّف)، أو سيكون الناتج هو ‎0 1 لأن المتغير x هو متغيرٌ في المجال العام والمتغير y لم يُصرَّح عنه قبل إسناد قيمته.

المتغيرات العامة غير المُصرَّح عنها

var x = 0;  // هذا المتغير عام وقيمته 0

console.log(typeof z); // undefined لأن المتغير ليس مُعرَّفًا بعد

function a() {
  var y = 2;   // هذا المتغير محلي وقيمته 2

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

  function b() {
    x = 3;  // إعادة إسناد القيمة إلى المتغير العام، ولن يُنشَأ متغيرٌ جديد
    y = 4;  // إعادة إسناد القيمة إلى المتغير العام، ولن يُنشَأ متغيرٌ جديد
    z = 5;  // إنشاء متغير عام جديد وإسناد القيمة 5 له
  }         // (سيرمي ReferenceError في النمط strict)

  b();     // استدعاء هذه الدالة سيؤدي إلى إنشاء المتغير z
  console.log(x, y, z);  // 3 4 5
}

a();                   // هذه الدالة ستستدعي الدالة b
console.log(x, z);     // 3 5
console.log(typeof y); // undefined لأن هذا المتغير محلي

دعم المتصفحات

الميزة Chrome Firefox Internet Explorer Opera Safari
الدعم الأساسي نعم نعم نعم نعم نعم

مصادر ومواصفات