المقدمة

هنتكلم في المقالة ديه عن إجراء مهم تقوم به الجافاسكريبت وهو ال hoisting ومعناه بالعربي "الرفع" وهو ان الجافاسكريبت تقوم برفع تعريف المتغيرات والدوال إلى أعلى النطاق (scope) سواء كان global scope أو اذا كان بداخل دالة فتقوم برفعه إلى أعلى نطاق الدالة (function scope) مما يجعلهم متاحين للاستخدام قبل تعريفهم.


كيفية عمل الـ Hoisting مع الـ Variables

طريقة إجراء ال hoisting ليست ثابتة بل تعتمد علي كيف تم تعريف المتغير.

استخدام Var

console.log(data); // undefined
var data = 5;

في هذا المثال من المتوقع ظهور خطأ لأني استخدمت المتغير قبل تعريفه ولكن النتيجة كانت(undefined) معناها انه تم تعريفه ولكن لا يحتوي علي قيمة وهنا اللي حصل كما هو و

موضح في الصورة أنه تم رفع تعريف المتغير إلي أعلي ال scope بالشكل ده واعطاءه قيمة تساوي undefined. وده نتيجة غريبة وغير منطقية وعشان كده بطلنا نستخدم var في الكود بتاعنا وبقينا نستخدم let و const.

// behind the scene
var data = undefined;
console.log(data); // undefined
data = 5;

استخدام Let & Const

console.log(data); // ReferenceError: Cannot access 'data' before initialization
let data = 5;
console.log(data); // ReferenceError: Cannot access 'data' before initialization
const data = 5;

هنا ظهر خطأ منطقي وهو انه مش ممكن استخدام المتغير قبل تعريفه ومن هنا ممكن نستنتج انه محصلش hoisting للمتغيرات في حالة استخدام let و const ولكن في الحقيقة هو حصل ليهم hoisting ولكن لا يمكن استخدامهم إلا بعد تعيين قيمة لهم وهنا نيجي لمفهوم مهم خاص ب let و const وهو (Temporal Dead Zone,TDZ) وهي باختصار المنطقة اللي تم عمل hoisting للمتغير فيها ولكن لا يمكن استخدامه الا بعد تعيين قيمة له. 

اذا تريد معرفة المزيد عن TDZ من هنا


كيفية عمل الـ Hoisting مع الـ Functions

هنا برضه زي المتغيرات هيختلف طريقة الإجراء على حسب ازاي تم تعريف الدالة.

استخدام الـ Function Declaration

console.log(addDecl(2, 3)); // 5
function addDecl(a, b) {
  return a + b;
}

 هنلاقي هنا انه تم عمل hoisting للدالة كلها بقيمتها الحقيقية.


استخدام الـ Var

console.log(addExprWithVar(2, 3)); // TypeError: addExprWithVar is not a function
var addExprWithVar = function(a, b) {
  return a + b;
};

هنا هيتم التعامل مع الدالة زي المتغير في أول مثال شرحناه والنتيجة منطقية لأنه بسبب var هيتم تعيين قيمة الدالة ب undefined ثم عمل call ل undefined.


استخدام Let & Const

console.log(addExpr(2, 3)); // ReferenceError: Cannot access 'addExpr' before initialization
const addExpr = function(a, b) {
  return a + b;
};

هنا هنلاقي برضه نفس النتيجة اللي حصلت قبل كده مع let و const وهو حدوث hoisting ولكن لا يمكن استخدام الدالة الا بعد تعيين القيمة لها.  


في الختام

ده جدول يلخص ازاي ال hoisting بيشتغل مع انواع المتغيرات المختلفة. 

Hoisting in JavaScript