الفرق بين المراجعتين لصفحة: «JavaScript/var»
لا ملخص تعديل |
ط استبدال النص - '\[\[تصنيف:(.*)\]\]' ب'{{SUBPAGENAME}}' |
||
سطر 159: | سطر 159: | ||
* معيار [http://www.ecma-international.org/ecma-262/5.1/#sec-12.2 ECMAScript 5.1]. | * معيار [http://www.ecma-international.org/ecma-262/5.1/#sec-12.2 ECMAScript 5.1]. | ||
* معيار [http://www.ecma-international.org/publications/files/ECMA-ST-ARCH/ECMA-262,%201st%20edition,%20June%201997.pdf ECMAScript 1st Edition] . | * معيار [http://www.ecma-international.org/publications/files/ECMA-ST-ARCH/ECMA-262,%201st%20edition,%20June%201997.pdf ECMAScript 1st Edition] . | ||
[[تصنيف:JavaScript]] | [[تصنيف:JavaScript|{{SUBPAGENAME}}]] | ||
[[تصنيف:JavaScript Statement]] | [[تصنيف:JavaScript Statement|{{SUBPAGENAME}}]] |
مراجعة 15:36، 28 يناير 2018
تعبير 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 |
---|---|---|---|---|---|
الدعم الأساسي | نعم | نعم | نعم | نعم | نعم |
مصادر ومواصفات
- مسودة المعيار ECMAScript Latest Draft.
- معيار ECMAScript 2015 (6th Edition).
- معيار ECMAScript 5.1.
- معيار ECMAScript 1st Edition .