فهم وحل خطأ TypeError: Cannot read property ‘split’ of undefined في JavaScript

دقائق القراءة: 7

مقدمة: فك شفرة خطأ TypeError: Cannot read property 'split' of undefined

إذا كنت مطور JavaScript، فمن المحتمل أن تكون قد واجهت خطأ TypeError: Cannot read property 'split' of undefined أثناء عملك. هذا الخطأ شائع بشكل خاص عند التعامل مع سلاسل النصوص (strings) والمصفوفات (arrays). على الرغم من أن رسالة الخطأ قد تبدو معقدة للوهلة الأولى، إلا أن السبب وراءها غالبًا ما يكون بسيطًا ويتعلق بسوء فهم أساسي لكيفية عمل دالة split() وكيفية التكرار عبر عناصر المصفوفات.

في هذا المقال، سنقوم بتشريح هذا الخطأ، وفهم أسبابه الجذرية، وتقديم حلول عملية وواضحة لتجنبه وحل المشكلات المتعلقة به، مع التركيز على بناء محتوى قيم ومفيد.

التعمق في دالة split() في JavaScript

دالة split() هي إحدى الدوال المدمجة القوية في JavaScript، والتي تُستخدم لتقسيم سلسلة نصية (string) إلى مصفوفة من السلاسل الفرعية (substrings). تعتمد عملية التقسيم هذه على مُحدّد (separator) يتم تمريره كمعامل للدالة. إليك كيفية عملها:

  • عند استدعاء split() على سلسلة نصية، تقوم الدالة بتقسيم السلسلة بناءً على المُحدّد الذي تم تمريره.
  • إذا تم تمرير سلسلة نصية فارغة ("") كمعامل، فإن split() تتعامل مع كل حرف في السلسلة الأصلية كسلسلة فرعية منفصلة.
  • الناتج دائمًا يكون مصفوفة تحتوي على السلاسل الفرعية الناتجة عن عملية التقسيم.

لنلقِ نظرة على بعض الأمثلة التوضيحية:

const testStr1 = "Test test 1 2";
const testStr2 = "cupcake pancake";
const testStr3 = "First,Second,Third";

testStr1.split(" "); // [ 'Test', 'test', '1', '2' ]
testStr2.split(""); // [ 'c', 'u', 'p', 'c', 'a', 'k', 'e', ' ', 'p', 'a', 'n', 'c', 'a', 'k', 'e' ]
testStr3.split(","); // [ 'First', 'Second', 'Third' ]

لمزيد من التفاصيل حول دالة split()، يمكنك الرجوع إلى توثيق MDN.

تحليل المشكلة: لماذا يظهر خطأ 'split' of undefined؟

فهم ما تُرجعه دالة split() وعدد السلاسل الفرعية التي تتوقعها هو المفتاح لحل هذا النوع من الأخطاء. لنعد إلى المثال الشائع الذي يسبب هذا الخطأ، والذي قد يصادفه البعض عند محاولة حل تحدي “إيجاد أطول كلمة في سلسلة نصية” (Find the Longest Word in a String):

function findLongestWord ( str ) {
  for ( let i = 0 ; i < str.length; i++) {
    const array = str.split( " " );
    array[i].split( "" );
  }
}

findLongestWord( "The quick brown fox jumped over the lazy dog" );

عند تشغيل هذا الكود، سيتم إلقاء الخطأ TypeError: Cannot read property 'split' of undefined. فلماذا يحدث ذلك؟

الخلط بين طول السلسلة وطول المصفوفة

الجزء الأول من الكود، const array = str.split(" ");، يعمل كما هو متوقع. إذا كانت قيمة str هي "The quick brown fox jumped over the lazy dog"، فإن array ستكون [ 'The', 'quick', 'brown', 'fox', 'jumped', 'over', 'the', 'lazy', 'dog' ].

المشكلة تكمن في حلقة التكرار for. لاحظ الشرط المستخدم للتكرار: i < str.length. هنا، يتم استخدام طول السلسلة الأصلية str كشرط للتكرار، وليس طول المصفوفة array الناتجة عن التقسيم.

إذا قمت بتسجيل str.length في وحدة التحكم (console)، فستجد أنها 44 (عدد الأحرف في السلسلة). بينما طول المصفوفة array هو 9 (عدد الكلمات). هذا يعني أن حلقة التكرار ستحاول الوصول إلى عناصر في array تتجاوز حدودها.

العبارة الأخيرة داخل جسم حلقة for هي التي تسبب الخطأ:

array[i].split("");

عندما تتجاوز قيمة i طول المصفوفة array (أي عندما تصبح i أكبر من أو تساوي 9)، فإن array[i] ستُرجع القيمة undefined. وبما أن دالة split() لا يمكن استدعاؤها إلا على سلسلة نصية (string)، فإن محاولة استدعائها على undefined يؤدي إلى الخطأ TypeError: Cannot read property 'split' of undefined.

للتوضيح، لنضف console.log داخل الحلقة:

function findLongestWord ( str ) {
  for ( let i = 0 ; i < str.length; i++) {
    const array = str.split( " " );
    console.log(array[i]);
    // array[0]: "The"
    // array[1]: "quick"
    // array[2]: "brown"
    // ...
    // array[8]: "dog" (آخر عنصر صالح)
    // array[9]: undefined
    // array[10]: undefined
    // ...
    // array[43]: undefined
  }
}

findLongestWord( "The quick brown fox jumped over the lazy dog" );

كما يتضح، بمجرد أن تصبح array[i] هي undefined، فإن محاولة استدعاء .split("") عليها ستفشل وتُلقي الخطأ.

حل تحدي إيجاد أطول كلمة في سلسلة نصية باستخدام split()

الآن بعد أن فهمنا سبب المشكلة، دعنا ننتقل إلى كيفية حل تحدي “إيجاد أطول كلمة في سلسلة نصية” بشكل صحيح باستخدام دالة split().

الخوارزمية المقترحة لحل المشكلة

إليك الخطوات المنطقية التي يجب اتباعها:

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

تطبيق الحل خطوة بخطوة

لنطبق هذه الخوارزمية عمليًا:

1. تقسيم السلسلة إلى مصفوفة من الكلمات

أولاً، نقوم بتقسيم السلسلة str إلى مصفوفة من الكلمات الفردية باستخدام المسافة كمُحدّد:

function findLongestWordLength ( str ) {
  const array = str.split( " " );
}

2. إنشاء متغيّر لتتبع أطول طول كلمة

الآن، سننشئ متغيّرًا باسم maxLength (أو maxWordLength) لتتبع أطول طول كلمة، ونضبط قيمته الأولية على صفر:

function findLongestWordLength ( str ) {
  const array = str.split( " " );
  let maxLength = 0 ;
}

3. التكرار عبر المصفوفة باستخدام array.length

بما أن قيمة array أصبحت الآن ['The', 'quick', 'brown', 'fox', 'jumped', 'over', 'the', 'lazy', 'dog']، يمكننا استخدام array.length في حلقة for لضمان التكرار الصحيح:

function findLongestWordLength ( str ) {
  const array = str.split( " " );
  let maxLength = 0 ;
  for ( let i = 0 ; i < array.length; i++) {
    // هنا سيتم مقارنة أطوال الكلمات
  }
}

4. التحقق من طول كل كلمة

نكرر عبر مصفوفة الكلمات ونتحقق من طول كل كلمة. تذكر أن السلاسل النصية (strings) تحتوي أيضًا على خاصية length التي يمكنك استدعاؤها بسهولة للحصول على طول السلسلة:

function findLongestWordLength ( str ) {
  const array = str.split( " " );
  let maxLength = 0 ;
  for ( let i = 0 ; i < array.length; i++) {
    array[i].length;
  }
}

5. تحديث maxLength إذا كانت الكلمة الحالية أطول

استخدم عبارة if للتحقق مما إذا كان طول الكلمة الحالية (array[i].length) أكبر من maxLength. إذا كان الأمر كذلك، فاستبدل قيمة maxLength بقيمة array[i].length:

function findLongestWordLength ( str ) {
  const array = str.split( " " );
  let maxLength = 0 ;
  for ( let i = 0 ; i < array.length; i++) {
    if (array[i].length > maxLength) {
      maxLength = array[i].length;
    }
  }
}

6. إرجاع maxLength

أخيرًا، أعد قيمة maxLength في نهاية الدالة، بعد انتهاء حلقة for:

function findLongestWordLength ( str ) {
  const array = str.split( " " );
  let maxLength = 0 ;
  for ( let i = 0 ; i < array.length; i++) {
    if (array[i].length > maxLength) {
      maxLength = array[i].length;
    }
  }
  return maxLength;
}

// مثال للاستخدام:
console.log(findLongestWordLength("The quick brown fox jumped over the lazy dog")); // الناتج: 6 (لكلمة 'jumped')

الخلاصة التقنية

يُعد خطأ TypeError: Cannot read property 'split' of undefined من الأخطاء الشائعة التي يواجهها مطورو JavaScript، وغالبًا ما ينبع من محاولة استدعاء دالة split() على قيمة غير صالحة، مثل undefined. السبب الجذري في معظم الحالات هو سوء فهم لكيفية عمل حلقات التكرار أو الوصول إلى عناصر خارج نطاق المصفوفة. الحل يكمن في ضمان أن المتغير الذي يتم استدعاء split() عليه هو دائمًا سلسلة نصية، والتحقق من شروط حلقات التكرار لتتوافق مع طول المصفوفة التي يتم التعامل معها، وليس طول السلسلة الأصلية. باتباع الخطوات الموضحة في هذا المقال، يمكن للمطورين تجنب هذا الخطأ الشائع وبناء تعليمات برمجية أكثر قوة وموثوقية.

اترك تعليقاً

لن يتم نشر عنوان بريدك الإلكتروني. الحقول الإلزامية مشار إليها بـ *