Menu
العربية

URL و URLSearchParams في JavaScript: دليل عملي

تعرّف على كيفية تحليل الروابط وبنائها وتعديلها في JavaScript باستخدام URL و URLSearchParams — بدون Regex وبدون مشاكل في الترميز.

توقّف عن تحليل الـ URL بحِيَل النصوص

قبل ظهور واجهة URL، كان المطورون يقطّعون الروابط باستخدام split('?') وتعابير نمطية (regex)، ويتركون الباقي للحظ. كانت الطريقة تعمل في الغالب… إلى أن تحتوي القيمة على & أو = أو مسافة أو حرف غير ASCII، فتنهار كل الحسابات. المتصفّح و Node.js يوفّران لك مُحلِّلًا (parser) جاهزًا ومُتقَنًا، فاستخدمه.

index.js
Output
Click Run to see the output here.

استدعاءٌ واحد، وتحصل على كل أجزاء الرابط مُقسَّمة ومفكوكة الترميز بشكل صحيح. يرمي الـ constructor خطأً من نوع TypeError عند تمرير مُدخَل غير صالح، وهذا ما تريده عادةً — فالرابط التالف يجب أن يفشل بصوت عالٍ بدل أن يُمرِّر بياناتٍ فاسدة بصمت إلى بقية البرنامج.

قراءة معاملات الرابط في JavaScript

كل كائن URL يحتوي على خاصية .searchParams — وهي كائن من نوع URLSearchParams يتيح لك قراءة وتعديل الـ query string بسهولة:

index.js
Output
Click Run to see the output here.

بعض النقاط التي يجدر الانتباه إليها:

  • القيم تُعاد بعد فكّ الترميز تلقائيًا. فمثلًا ?name=Ada%20Lovelace ستحصل منه على "Ada Lovelace".
  • كل شيء هنا نصوص. "2" ليست 2. استخدم Number() إذا احتجت رقمًا فعليًا.
  • تكرار المفاتيح مسموح. الدالة get تُعيد أول تطابق، بينما getAll تُعيد كل التطابقات.
  • المفاتيح غير الموجودة تُعيد null لا undefined، ولذلك يعمل معها ?? "default" بشكل ممتاز.

بناء query string في JavaScript

تستطيع بناء query string من الصفر باستخدام URLSearchParams، دون الحاجة إلى ترميز يدوي ولا دمج بالرمز &:

index.js
Output
Click Run to see the output here.

أو يمكنك إنشاؤه انطلاقًا من كائن — أي iterable يحتوي على أزواج [key, value] يفي بالغرض، وحتى الكائن العادي يعمل أيضًا:

index.js
Output
Click Run to see the output here.

set مقابل append: الدالة set تستبدل أي قيمة موجودة مسبقاً لنفس المفتاح، بينما append تضيف قيمة جديدة إلى جانب القيم السابقة. استخدم append حين يكون من المنطقي تكرار المفتاح (مثل الوسوم أو الفلاتر)، واستخدم set للمعاملات ذات القيمة الواحدة.

تعديل رابط URL في جافا سكريبت

بما أن كائن URL كائن حيّ، فإن أي تغيير يطرأ على searchParams ينعكس تلقائياً على .search و.href:

index.js
Output
Click Run to see the output here.

هذه هي الطريقة المثالية لإضافة معامل (query parameter) إلى رابط موجود مسبقًا. بدون الحاجة إلى التحقق "هل الرابط يحتوي على ? أصلًا؟"، ولا القلق بشأن إضافة & أو ? في البداية.

ويمكنك تعديل أي جزء آخر من الرابط بنفس الأسلوب:

index.js
Output
Click Run to see the output here.

المرور على معاملات الرابط

الكائن URLSearchParams قابل للتكرار (iterable)، فباستخدام for...of تحصل على أزواج [key, value] مباشرةً، كما تتوفر الدوال المعتادة keys() وvalues() وentries():

index.js
Output
Click Run to see the output here.

لاحظ أن المفاتيح المكررة تظهر أكثر من مرة — سترى tag = web ثم tag = beginner كعنصرين منفصلين. وهذا يعكس بأمانة ما يحتويه الـ query string فعلياً.

وإذا أردت كائناً عادياً لطباعة سريعة بغرض التصحيح، فإن Object.fromEntries يفي بالغرض — لكن انتبه أنه يدمج المفاتيح المكررة ويحتفظ بآخر قيمة فقط:

index.js
Output
Click Run to see the output here.

جيد لأغراض التصحيح، لكنه خاطئ إذا كان أي مفتاح قد يتكرر.

الروابط النسبية تحتاج إلى base

لو جرّبت new URL("/search?q=js") لوحده، راح يرمي خطأ — المسار النسبي وحده ما يُعتبر رابطًا صالحًا. الحل إنك تمرّر رابطًا أساسيًا (base) كوسيط ثانٍ:

index.js
Output
Click Run to see the output here.

قواعد حلّ الروابط هنا هي نفسها التي يستخدمها المتصفح مع <a href>: الشرطة المائلة / في البداية تعني مسارًا مطلقًا من الـ host، وغيابها يعني أنّ المسار نسبي بالنسبة للمسار الحالي، بينما .. ترجع خطوة إلى الأعلى. مفيدة جدًا عندما تبني عناوين API انطلاقًا من base محدد مسبقًا.

في المتصفح، يصلح window.location.href كـ base جاهز لتحليل رابط الصفحة الحالية:

const u = new URL(window.location.href);
const page = u.searchParams.get("page") ?? "1";

التعامل مع روابط URL غير الصالحة

يطلق الـ constructor الخاص بـ URL استثناءً عند تمرير مدخل غير سليم. هذا السلوك مفيد فعلاً، لكنه يعني أنك ستحتاج إلى try/catch عند تحليل أي رابط كتبه المستخدم أو وصلك من نظام خارجي:

index.js
Output
Click Run to see the output here.

البيئات الحديثة توفر أيضًا URL.canParse(input) — وهي طريقة تُرجع قيمة منطقية (boolean) تُغنيك عن استخدام try/catch عندما يكون هدفك مجرد التحقق من صحة الرابط:

index.js
Output
Click Run to see the output here.

مثال عملي صغير

لنجمع كل ما سبق في مثال واحد: نقرأ الفلاتر الحالية من رابط URL، نعدّل عليها، ثم نبني رابطًا جديدًا للانتقال إليه:

index.js
Output
Click Run to see the output here.

تمرير null يحذف المعامل، وأي قيمة أخرى تضبطه أو تستبدله. هذا نمط ستجد نفسك تكتبه بشكل أو بآخر في كل مرة تبني فيها واجهات فلترة، أو ترقيم صفحات، أو روابط عميقة (deep links).

الخلاصة

  • new URL(string) يحلّل الرابط ويقسّمه إلى أجزاء مسمّاة، ويرمي استثناءً عند تمرير قيمة غير صالحة.
  • الخاصية url.searchParams هي كائن من النوع URLSearchParams — استعمل معها get وgetAll وset وappend وdelete وhas.
  • الترميز يحدث تلقائيًا، فلا حاجة للجوء إلى encodeURIComponent إلا إذا كنت تبني السلاسل يدويًا.
  • مرّر رابطًا أساسيًا كوسيط ثانٍ لحلّ المسارات النسبية.
  • استعمل URL.canParse (أو try/catch) للتحقق من صحة المدخلات غير الموثوقة.

في كل مرة تراودك فكرة تقطيع الرابط بـ .split('?') أو استخراج معامل من الـ query string عبر تعبير نمطي، توقّف واستخدم هذه الواجهات بدلًا من ذلك. فهي أقصر، وأصحّ، وموجودة أصلًا ضمن بيئة التشغيل.

الأسئلة الشائعة

كيف أحلّل رابط URL في JavaScript؟

مرّر النص إلى الـ constructor الخاص بـ URL هكذا: const u = new URL('https://example.com/path?x=1'). الكائن الناتج يوفّر لك protocol و host و pathname و search و hash، بالإضافة إلى searchParams. انتبه إلى أنه يرمي استثناءً عند تمرير رابط غير صالح، لذا من الأفضل تغليفه بـ try/catch عند التعامل مع مدخلات غير موثوقة.

كيف أحصل على قيمة معامل من الـ query string في JavaScript؟

استخدم url.searchParams.get('name')، وستُرجع القيمة بعد فكّ الترميز، أو null إذا لم يكن المعامل موجودًا. أما إذا كان المعامل قد يتكرر مثل ?tag=a&tag=b، فاستعمل searchParams.getAll('tag') للحصول على جميع القيم في مصفوفة.

ما الفرق بين URL و URLSearchParams؟

URL يمثّل الرابط كاملًا — البروتوكول والـ host والمسار والاستعلام والـ hash. بينما URLSearchParams مختصّ فقط بجزء الـ query string، ويمكن استخدامه بشكل مستقل لبناء أو تحليل نصوص مثل a=1&b=2. وكل كائن URL يحتوي على خاصية .searchParams وهي عبارة عن URLSearchParams مرتبطة بذلك الرابط.

هل أحتاج إلى ترميز معاملات الاستعلام يدويًا؟

لا. URLSearchParams يرمّز المفاتيح والقيم تلقائيًا عند استدعاء set أو append، وكذلك عند قراءة النص الناتج. يتعامل مع المسافات و & و = وحروف الـ Unicode بشكل صحيح. لا تلجأ إلى encodeURIComponent إلا إذا كنت تبني الرابط يدويًا بالكامل — وهو أمر يُفضَّل تجنّبه عادةً.

تعلّم البرمجة مع Coddy

ابدأ الآن