متى يجب استخدام var ، دع وابق في Javascript [ترجمة من Tyler McGinnis]

مرحبا يا هبر! أقدم إليكم ترجمة المقال "var vs let vs const في JavaScript" بواسطة Tyler McGinnis.

الصورة

في هذه المقالة ، سوف تتعلم طريقتين جديدتين لإنشاء متغيرات في Javascript (ES6) ، واسمحوا و const. خلال هذه المقالة ، سننظر في الاختلافات بين var ، واسمحوا ، و const ، وكذلك الموضوعات ذات الصلة مثل "نطاق الوظيفة مقابل نطاق الكتلة" ، و "رفع" المتغيرات ، وثبات.

إذا كنت تفضل مقطع فيديو ، شاهد هذا (الأصل باللغة الإنجليزية):


قدمنا ​​ES2015 (أو ES6) إلى طريقتين جديدتين لإنشاء المتغيرات ، واسمحوا و const . ولكن قبل الخوض في الاختلافات بين var ، واسمحوا ، و const ، هناك بعض المواضيع التي يجب أن تعرفها أولاً. هذه هي إعلان المتغيرات وتهيئتها ونطاقها (نطاق خاص للوظيفة) و "الرفع".

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


إعلان متغير يقدم معرف جديد.

var declaration 

أعلاه نحن إنشاء معرف جديد الذي أطلقنا عليه "إعلان". في Javascript ، عند إنشائه ، تتم تهيئة المتغيرات بقيمة غير محددة . هذا يعني أنه إذا حاولنا إخراج متغير الإعلان الخاص بنا ، فإننا نحصل على غير معرف .

 var declaration console.log(declaration) 

وهكذا ، استنتجنا متغير الإعلان وحصلنا على تعريف .

مقارنة بإعلان متغير ، فإن تهيئة متغير هي المرة الأولى التي تقوم فيها بتعيين قيمة هذا المتغير.

 var declaration console.log(declaration) // undefined declaration = '  ' 

وهكذا ، قمنا هنا بتهيئة متغير الإعلان عن طريق كتابة سلسلة إليه.

هذا يقودنا إلى المفهوم التالي ، النطاق.

النطاق


يصف النطاق المكان الذي يمكن الوصول إلى المتغير والوظائف فيه ضمن برنامجنا. في Javascript ، هناك نوعان من النطاقات - النطاق العالمي ، ونطاق الوظيفة . وفقا للمواصفات الرسمية ،
"في حالة حدوث إعلان متغير داخل إعلان دالة ، يتم تعريف المتغير في النطاق المحلي لهذه الوظيفة ..."
هذا يعني أنه إذا قمت بإنشاء متغير باستخدام var ، فسيكون نطاق هذا المتغير هو الوظيفة التي تم إنشاؤه به وسيكون متاحًا فقط داخل هذه الوظيفة أو أي وظيفة متداخلة أخرى.

 function getDate () { var date = new Date() return date } getDate() console.log(date) // NOT OK: Reference Error 

أعلاه ، حاولنا الوصول إلى المتغير من خارج الوظيفة التي تم الإعلان عنها. نظرًا لأن نطاق متغير التاريخ هو وظيفة getDate ، فهي متاحة فقط داخل هذه الوظيفة أو في أي وظيفة أخرى متداخلة في getDate (كما هو موضح أدناه).

 function getDate () { var date = new Date() function formatDate () { return date.toDateString().slice(4) // OK } return formatDate() } getDate() console.log(date) // NOT OK: Reference Error 

الآن دعونا نلقي نظرة على مثال أكثر تقدما. دعنا نقول أن لدينا مجموعة من الأسعار ونحن بحاجة إلى وظيفة تأخذ هذه المجموعة ، وكذلك متغير خصم ، وتعيد إلينا مجموعة جديدة من الأسعار بخصومات. قد يبدو الهدف النهائي مثل هذا:

 discountPrices([100, 200, 300], .5) 

وقد يبدو التنفيذ كالتالي:

 function discountPrices (prices, discount) { var discounted = [] for (var i = 0; i < prices.length; i++) { var discountedPrice = prices[i] * (1 - discount) var finalPrice = Math.round(discountedPrice * 100) / 100 discounted.push(finalPrice) } return discounted } 

تبدو بسيطة بما فيه الكفاية ، ولكن ما علاقة هذا بنطاق الكتلة؟ نلقي نظرة على هذا للحلقة. هل المتغيرات المعلنة بداخلها يمكن الوصول إليها خارجها؟ اتضح المتاحة.

 function discountPrices (prices, discount) { var discounted = [] for (var i = 0; i < prices.length; i++) { var discountedPrice = prices[i] * (1 - discount) var finalPrice = Math.round(discountedPrice * 100) / 100 discounted.push(finalPrice) } console.log(i) // 3 console.log(discountedPrice) // 150 console.log(finalPrice) // 150 return discounted } 

إذا كانت JavaScript هي لغة البرمجة الوحيدة التي تعرفها ، فقد لا داعي للقلق بشأن ذلك كثيرًا. ومع ذلك ، إذا أتيت إلى جافا سكريبت من لغة برمجة أخرى ، خاصة لغة البرمجة التي تحجب النطاق ، فمن المحتمل أن تكون قلقًا بشأن ما يحدث هنا.

ليست مكسورة ، وأنها تعمل فقط غريب بعض الشيء. لا يوجد حقًا سبب للوصول إلى i و discountPrice و finalPrice خارج حلقة for . لا يفيدنا أي شيء ، وقد يؤذينا حتى في بعض الحالات. ومع ذلك ، نظرًا لأن المتغيرات يتم الإعلان عنها باستخدام var ، فإنها تقع في نطاق الوظيفة ويمكنك الوصول إليها.

لقد ناقشنا الآن الإعلان وتهيئة المتغيرات ، وكذلك النطاق ، وهو شيء آخر نحتاج إلى التعامل معه قبل أن نتعمق في الاختلافات بين let و const ، وهذا "يثير".

"ارفع"


تذكر أنه قيل سابقًا ، "في Javascript ، عند الإنشاء ، تتم تهيئة المتغيرات بالقيمة غير المحددة". اتضح أن هذا يعني "رفع". يقوم مترجم جافا سكريبت JavaScript بتعيين المتغيرات المعلنة على غير معرف أثناء مرحلة تسمى "إنشاء".

للحصول على دراسة أكثر تفصيلاً عن مرحلة الإنشاء ، "النهوض" والنطاقات ، اقرأ هذه المقالة: "الدليل النهائي للرفع ، النطاقات ، والإغلاقات في JavaScript" .

دعنا نلقي نظرة على المثال السابق ونرى كيف "رفع" يؤثر عليه.

 function discountPrices (prices, discount) { var discounted = undefined var i = undefined var discountedPrice = undefined var finalPrice = undefined discounted = [] for (var i = 0; i < prices.length; i++) { discountedPrice = prices[i] * (1 - discount) finalPrice = Math.round(discountedPrice * 100) / 100 discounted.push(finalPrice) } console.log(i) // 3 console.log(discountedPrice) // 150 console.log(finalPrice) // 150 return discounted } 

لاحظ أنه تم ضبط جميع المتغيرات المعلنة على غير محدد . لهذا السبب ، إذا حاولت الوصول إلى أحدهم قبل الإعلان عنه فعليًا ، فستصبح غير محدد .

 function discountPrices (prices, discount) { console.log(discounted) // undefined var discounted = [] for (var i = 0; i < prices.length; i++) { var discountedPrice = prices[i] * (1 - discount) var finalPrice = Math.round(discountedPrice * 100) / 100 discounted.push(finalPrice) } console.log(i) // 3 console.log(discountedPrice) // 150 console.log(finalPrice) // 150 return discounted } 

الآن أنت تعرف كل ما تحتاجه حول var ، والآن دعنا نتحدث أخيرًا عن الهدف الرئيسي الذي نحن هنا من أجله: ما الفرق بين var ، let و const ؟

فار ، واسمحوا أو const


للبدء ، دعونا نقارن var وندع . يتمثل الاختلاف الرئيسي بين var و let في أن نتيح لك تحديد المتغيرات في نطاق الكتلة ، بغض النظر عن النطاق العام ونطاق الوظيفة. هذا يعني أن المتغير الذي تم إنشاؤه باستخدام الكلمة الأساسية let متاح داخل "الكتلة" حيث تم إنشاؤه ، وكذلك داخل الكتل المتداخلة. عندما قلت "كتلة" ، كنت أقصد شيئًا محاطًا بأقواس مجعدة {} ، مثل حلقة for أو عبارة if .

وهكذا ، دعونا نعود إلى وظيفة discountPrices لدينا للمرة الأخيرة.

 function discountPrices (prices, discount) { var discounted = [] for (var i = 0; i < prices.length; i++) { var discountedPrice = prices[i] * (1 - discount) var finalPrice = Math.round(discountedPrice * 100) / 100 discounted.push(finalPrice) } console.log(i) // 3 console.log(discountedPrice) // 150 console.log(finalPrice) // 150 return discounted } 

تذكر أن لدينا الحق في إخراج i و discountPrice و finalPrice خارج الحلقة for ، حيث تم الإعلان عنهم باستخدام var ، والمتغيرات المعلنة باستخدام الكلمة var مقيدة بنطاق الوظيفة. ولكن ماذا يحدث الآن إذا قمنا بتغيير var للسماح ومحاولة تشغيل التعليمات البرمجية الخاصة بنا؟

 function discountPrices (prices, discount) { let discounted = [] for (let i = 0; i < prices.length; i++) { let discountedPrice = prices[i] * (1 - discount) let finalPrice = Math.round(discountedPrice * 100) / 100 discounted.push(finalPrice) } console.log(i) // 3 console.log(discountedPrice) // 150 console.log(finalPrice) // 150 return discounted } discountPrices([100, 200, 300], .5) // NOT OK: ReferenceError: i is not defined 

لقد حصلنا على ReferenceError: أنا غير معرف . الذي يخبرنا أن المتغير المُعلَن بـ let يقتصر على نطاق الكتلة وليس الوظيفة. حاول الاتصال بـ i (أو بأسعار مخفضة أو السعر النهائي ) خارج "الحظر" حيث تم الإعلان عنهم ، وهذا سيعطينا خطأ في الاتصال ، كما رأينا للتو.

 var VS let var:     let:     

ترتبط الاختلافات التالية بـ "الرفع". قلنا سابقًا أن تعريف "الرفع" هو: "يقوم مترجم جافا سكريبت بتعيين المتغيرات المعلنة إلى غير محددة خلال المرحلة المسماة" إنشاء "." لقد رأينا هذا أيضًا في العمل عن طريق استدعاء المتغير قبل إعلانه (حصلت على غير محدد ).

 function discountPrices (prices, discount) { console.log(discounted) // undefined var discounted = [] for (var i = 0; i < prices.length; i++) { var discountedPrice = prices[i] * (1 - discount) var finalPrice = Math.round(discountedPrice * 100) / 100 discounted.push(finalPrice) } console.log(i) // 3 console.log(discountedPrice) // 150 console.log(finalPrice) // 150 return discounted } 

لا يمكنني تذكر حالة استخدام واحدة عندما ترغب حقًا في الوصول إلى متغير قبل الإعلان عنه. يبدو أن الحصول على ReferenceError سيكون أفضل من الحصول على غير محدد .

في الواقع ، هذا هو ما يدعنا نفعله. إذا حاولت الوصول إلى متغير قبل إعلانه باستخدام let ، فبدلاً من الحصول على غير محدد (كما كان عند الإعلان باستخدام var ) ، ستحصل على ReferenceError .

 function discountPrices (prices, discount) { console.log(discounted) // NOT OK: ReferenceError let discounted = [] for (let i = 0; i < prices.length; i++) { let discountedPrice = prices[i] * (1 - discount) let finalPrice = Math.round(discountedPrice * 100) / 100 discounted.push(finalPrice) } console.log(i) // 3 console.log(discountedPrice) // 150 console.log(finalPrice) // 150 return discounted } 

 var VS let var:        undefined         . let:       ReferenceError        . 

اسمحوا أو const


الآن أنت تفهم الفرق بين فار واسمحوا ، ماذا عن const؟ اتضح أن const هو تقريبا نفس اسمحوا. ومع ذلك ، هناك اختلاف واحد: إذا قمت بتعيين قيمة مرة واحدة باستخدام const ، فلا يمكنك تغييرها إلى أخرى.

 let name = 'Tyler' const handle = 'tylermcginnis' name = 'Tyler McGinnis' // OK handle = '@tylermcginnis' // NOT OK: TypeError: Assignment to constant variable. 

الاستنتاج مما سبق هو أنه يمكن الكتابة فوق المتغيرات المعلنة بـ let ، وأن المتغيرات المعلنة بـ const لا يمكن الكتابة عليها.

عظيم ، الآن بعد أن تريد أن يكون المتغير ثابتًا ، يمكنك إعلانه باستخدام const . أو ليس حقا. لمجرد أنه تم الإعلان عن متغير باستخدام const لا يعني أنه غير قابل للتغيير ، كل هذا يعني أنه لا يمكن الكتابة فوقه. أدناه مثال جيد.

 const person = { name: 'Kim Kardashian' } person.name = 'Kim Kardashian West' // OK person = {} // NOT OK: Assignment to constant variable. 

لاحظ أن تغيير خاصية كائن ليس بالكتابة الفوقية ، لذلك حتى لو تم التصريح عن استخدام الكائن const ، فإن هذا لا يعني أنه لا يمكنك تغيير أي من خصائصه. هذا يعني فقط أنه لا يمكنك الكتابة فوق هذا الكائن.

الآن ، أهم سؤال لم تتم الإجابة عليه بعد: ما الذي يجب أن أستخدمه var أو let أو const ؟ الرأي الأكثر شعبية ، والذي أوافق عليه ، هو استخدام const دائمًا حتى تعرف ما إذا كان المتغير سيتغير. السبب في ذلك هو أن استخدام const يجعلك واضحا لنفسك ومطوري المستقبل الذين يجب أن يقرأوا الكود الخاص بك بأنه لا ينبغي تغيير هذا المتغير. إذا كنت بحاجة إلى تغييره (على سبيل المثال في حلقة for ) ، فما عليك سوى استخدام let .

لم يتبق الكثير من الحالات بين المتغيرات التي تتغير والمتغيرات التي لا تتغير. هذا يعني أنك لن تضطر إلى استخدام فار مرة أخرى.

الآن ، فإن الرأي الذي لا يحظى بشعبية ، على الرغم من أنه لا يزال لديه مبرر ، هو أنه يجب عليك عدم استخدام const ، على الرغم من أنك تحاول إظهار أن هذا المتغير غير قابل للتغيير ، كما رأينا أعلاه ، هذا ليس صحيحًا تمامًا. دائمًا ما يستخدم مطورو البرامج الذين يحملون هذا الرأي طالما لا توجد متغيرات تشكل بالفعل ثوابت ، مثل _LOCATION_ = ....

لنعد ملخصًا لما ورد أعلاه ، يكون فار مقيدًا بنطاق الوظيفة وإذا حاولت الوصول إلى هذا المتغير قبل إعلانه ، فسوف تحصل على غير معرف . const و اسمحوا يقتصر نطاق الكتلة ، وإذا حاولت الوصول إلى هذه المتغيرات قبل إعلانها ، فستحصل على ReferenceError . والفرق بين const و let هو أنه لا يمكن الكتابة فوق القيمة التي تم تعيينها إلى const ، على عكس let .

 var VS let VS const var:        undefined         . let:       ReferenceError        . const:       ReferenceError        .     

تم نشر هذا المقال في الأصل على tylermcginnis.com كجزء من دورة جافا سكريبت الحديثة .

شكرا لقراءتك هذه الترجمة ، أتمنى أن تقابل شيئًا جديدًا ومفيدًا لك. سأكون سعيدا لرؤية ردود الفعل!

Source: https://habr.com/ru/post/ar438880/


All Articles