أنواع الإشارة ECMAScript

يُسمى النوع المشار إليه عادةً بكلاً (class).

هذا الدليل سيتم مناقشة العديد من أنواع الاستدلال المسبق لـ ECMAScript.

نوع المشار إليه

يُسمى النوع المشار إليه عادةً بكلاً (class)، مما يعني أن العنصر الذي يتم التعامل معه هو عنصر.

هذا الدليل سيتم مناقشة العديد من أنواع الاستدلال المسبق لـ ECMAScript.

من الآن فصاعدًا، سنركز على النوع المشار إليه، وهو نوع مرتبط بشكل وثيق بالنوع الأساسي الذي تم مناقشته.

ملاحظة:من الناحية التقليدية، ECMAScript لا يمتلك كلاً حقيقيًا. في الواقع، لا يوجد كلمة "كلاً" في ECMA-262، ويُشار إلى عدم وجود كلاً. يعرف ECMAScript "تعريف العنصر"، وهو شبيه منطقيًا بكلاً في لغات البرمجة الأخرى.

نصيحة:سيستخدم هذا الدليل مصطلح "عنصر".

يتم إنشاء العنصر عن طريق استخدام عميل new مع اسم العنصر الذي يتم استخدامه للاستنساخ. على سبيل المثال، يقوم الكود التالي بإنشاء نموذج من العنصر Object:

var o = new Object();

هذه الجملة مشابهة لغة Java، ولكن عندما يكون هناك أكثر من معامل، يتطلب ECMAScript استخدام الكوerdale. يمكن تقييد الكوerdale إذا لم يكن هناك معامل، كما في الكود التالي:

var o = new Object;

ملاحظة:على الرغم من أن الكوerdale ليست ضرورية، ولكن من أجل تجنب الالتباس، من الأفضل استخدام الكوerdale.

نصيحة:سنقوم بمناقشة العناصر بشكل أعمق في فصل أساسيات العناصر.

النقطة الرئيسية لهذا الفصل هي أنواع الإشارات التي لها أنواع أصلية مشابهة.

عنصر Object

العنصر Object غير مفيد بشكل كبير، ولكن قبل فهم الأنواع الأخرى، يجب أن نتعرف عليه. لأن العنصر Object في ECMAScript يشبه java.lang.Object في Java، جميع الأنواع في ECMAScript تستمر في هذا العنصر، وكل الخصائص والمتغيرات في العنصر Object ستظهر في الأنواع الأخرى، لذا يمكننا فهم العنصر Object بشكل أفضل.

يملك عنصر Object العدة خصائص:

constructor
الإشارة إلى الدالة التي أنشأت العنصر (الإشارة). بالنسبة للاعتبارات Object، يشير هذا الإشارة إلى الدالة الأصلية Object().
Prototype
الإشارة إلى原型 العنصر. بالنسبة لجميع العناصر، يعود افتراضياً نموذج Object.

يملك عنصر Object عدة طرق:

hasOwnProperty(property)
تحديد ما إذا كان العنصر يحتوي على خاصية معينة. يجب تحديد هذه الخاصية باستخدام نص (مثلاً، o.hasOwnProperty("name"))
IsPrototypeOf(object)
تحديد ما إذا كان العنصر هو نموذج آخر للعنصر.
PropertyIsEnumerable
تحديد ما إذا كان يمكن استخدام خاصية معينة بـ for...in.
ToString()
يعود تمثيل النص الأصلي للعنصر. بالنسبة للاعتبارات Object، لم يحدد ECMA-262 هذه القيمة، لذا تختلف القيم بين التنفيذات المختلفة لـ ECMAScript.
ValueOf()
يعود القيمة الأصلية الأكثر ملاءمة للعنصر. بالنسبة لكثير من العناصر، القيمة التي تعودها هذه الطريقة هي نفس القيمة التي تعودها طريقة ToString().

ملاحظة:سيقوم بغطاء كل الخاصية والطريقة المذكورة أعلاه بكائن آخر.}

كائن Boolean

كائن Boolean هو نوع مرجعي لنوع Boolean الأصل.

لإنشاء كائن Boolean، يكفي تمرير قيمة Boolean كمعامل:

var oBooleanObject = new Boolean(true);

سيقوم كائن Boolean بتغطية طريقة ValueOf() لكائن Object، لإرجاع القيمة الأصلية، وهي true وfalse. سيقوم أيضًا بتغطية طريقة ToString()، لإرجاع النص "true" أو "false".

للأسف، يتم استخدام كائنات Boolean بشكل نادر في ECMAScript، حتى إذا تم استخدامها، فإنها ليست سهلة الفهم.

يظهر عادةً المشكلة عند استخدام كائنات Boolean في التعبيرات الثنائية. على سبيل المثال:

var oFalseObject = new Boolean(false);
var bResult = oFalseObject && true;	//يتم إرجاع true

في هذا الشيفرة، يتم إنشاء كائن Boolean باستخدام القيمة false. ثم يتم استخدام هذه القيمة مع القيمة الأصلية true في عمليات AND في الحسابات الثنائية، والنتيجة هي false. ومع ذلك، في هذا السطر من الشيفرة، يتم حساب oFalseObject وليس قيمته false.

كما تم مناقشته سابقًا، في التعبيرات الثنائية، يتم تحويل جميع الكائنات تلقائيًا إلى true، لذا القيمة الخاصة بكائن oFalseObject هي true. ثم يتم إجراء عمليات AND مع true، والنتيجة هي true.

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

الاستشارة

للحصول على معلومات إضافية حول كائن Boolean، يرجى زيارة دليل الجسر لـ JavaScript Boolean.

كائن Number

كما تتوقع، كائن Number هو نوع مرجعي لعدد الأصل. لإنشاء كائن Number، استخدم الشيفرة التالية:

var oNumberObject = new Number(68);

من المتوقع أن تكون قد لاحظت في الفقرات السابقة من هذا الفصل مناقشة عدد الأعداد الخاصة (مثل Number.MAX_VALUE) عندما تم ذكر كائن Number. جميع القيم الخاصة هي خصائص ثابتة لكائن Number.

للحصول على القيمة الأصلية لعدد الديجيتال، يكفي استخدام طريقة valueOf():

var iNumber = oNumberObject.valueOf();

بالطبع، لدى فئة Number أيضًا طريقة toString()، تم مناقشتها بشكل دقيق في الفصل المتعلق بتحويل الأنواع.

إضافة إلى الطرق القياسية التي يتم استدعاؤها من Object، لدى Object Number أيضًا بعض الطرق المتخصصة في معالجة الأرقام.

طريقة toFixed()

تعود طريقة toFixed() بتمثيل الأرقام التي تحتوي على عدد محدد من الأرقام العشرية. على سبيل المثال:

var oNumberObject = new Number(68);
alert(oNumberObject.toFixed(2));  //يُعرض "68.00"

في هذا السياق، يكون متغير طريقة toFixed() هو 2، مما يعني أن يجب عرض اثنين من الأرقام العشرية. تعود هذه الطريقة بـ "68.00"، ويتم تعويض الفواصل الخالية بالأصفار. هذه الطريقة مفيدة جدًا في التطبيقات المتعلقة بالمال، حيث يمكن لطريقة toFixed() تمثيل الأرقام التي تحتوي على من 0 إلى 20 من الأرقام العشرية، ويُحدث أي قيمة تتجاوز هذا النطاق خطأ.

طريقة toExponential()

طريقة أخرى مرتبطة بتنسيق الأرقام هي toExponential()، التي تعود بتمثيل الأرقام باستخدام الشكل العلمي للتمثيل.

مثل طريقة toFixed()، لديها أيضًا متغيرًا معينًا يحدد عدد الأرقام العشرية التي يجب عرضها. على سبيل المثال:

var oNumberObject = new Number(68);
alert(oNumberObject.toExponential(1));  //يُعرض "6.8e+1"

نتيجة هذا الكود هي "6.8e+1"، كما تم شرحه سابقًا، يمثل 6.8x101المشكلة هي ماذا إذا لم يكن يعلم أي شكل يجب استخدامه (الشكل المسبق أو الشكل المعياري) لتمثيل الرقم؟ يمكن استخدام طريقة toPrecision().

طريقة toPrecision()

يستخدم طريقة toPrecision() لتحويل الرقم إلى شكل مسبق أو شكل معياري بناءً على الشكل الأكثر أهمية. لديها متغير واحد وهو عدد الأرقام المستخدمة لتمثيل الرقم (باستثناء القاعدة). على سبيل المثال،

var oNumberObject = new Number(68);
alert(oNumberObject.toPrecision(1));  //يُعرض "7e+1"

مهمة هذا الكود هي تمثيل الرقم 68 برقم واحد، النتيجة هي "7e+1"، ويمكن تمثيله بشكل آخر وهو 70. بالتأكيد، يقوم طريقة toPrecision() بتعديل الأرقام.

var oNumberObject = new Number(68);
alert(oNumberObject.toPrecision(2));  //يُعرض "68"

بالطبع، الناتج هو "68"، لأن هذا هو تمثيل الدالة الدقيق لهذا الرقم. ولكن ماذا إذا كان عدد الأرقام المحدد أكبر من الأرقام المطلوبة؟

var oNumberObject = new Number(68);
alert(oNumberObject.toPrecision(3));  //يخرج "68.0"

في هذه الحالة، toPrecision(3) تساوي toFixed(1)، الناتج هو "68.0".

methods toFixed() و toExponential() و toPrecision() تقوم بإجراء عمليات تقريب لتمثيل الرقم بالعدد الصحيح من الأرقام العشرية.

نصيحة:مثل Object Boolean، Object Number مهم جدًا، ولكن يجب ألا يستخدم هذا النوع من الإشارات إلا في الحالات الضرورية لتجنب المشاكل المحتملة. يجب استخدام تمثيلات الأرقام الأساسية عند الممكن.

الاستشارة

للحصول على معلومات إضافية حول Object Number، يرجى زيارة دليل الجسر لـ JavaScript Number.

Object String

Object String هو تمثيل لـ String النوع الأساسي، ويُصنع بهذه الطريقة:

var oStringObject = new String("hello world");

methods valueOf() و toString() لـ Object String ستعود إلى القيمة الأصلية لنوع String:

alert(oStringObject.valueOf() == oStringObject.toString());	//يخرج "true"

إذا تم تشغيل هذا الكود، الناتج هو "true"، مما يعني أن هذه القيم متساوية حقًا.

ملاحظة:Object String هو واحد من أنواع الإشارات المعقدة في ECMAScript. كما أن هدف هذا الفصل هو فقط معرفة وظائف String الأساسية. يمكنك قراءة الفصول ذات الصلة في هذا الدليل أو الاستعانة بالكتب الموصى بها. دليل الجسر لـ JavaScript String.

خاصية length

يملك Object String خاصية length، وهي عدد الحروف في النص:

var oStringObject = new String("hello world");
alert(oStringObject.length);	//يخرج "11"

النص الذي يخرج به هذا المثال هو "11"، وهو عدد الحروف في "hello world". لاحظ، حتى لو كان النص يحتوي على أحرف ثنائية الحزم (مقارنة بحروف ASCII التي تستخدم حزمة واحدة)، فإن كل حرف يعتبر حرفًا واحدًا.

methods charAt() و charCodeAt()

يملك Object String العديد من methods.

أولاً، كلاً من methods charAt() و charCodeAt() يصلان إلى حرف واحد داخل النص. كلاً من هذين الدوال لهما متغير واحد، وهو موضع الحرف الذي يتم معالجته.

charAt() يرجع إليه نص يحتوي على الحرف في الموضع المحدد:

var oStringObject = new String("hello world");
alert(oStringObject.charAt(1));	//يخرج "e"

在字符串 "hello world" 中,位置 1 处的字符是 "e"。在“ECMAScript 原始类型”这一节中我们讲过,第一个字符的位置是 0,第二个字符的位置是 1,依此类推。因此,调用 charAt(1) 返回的是 "e"。

如果想得到的不是字符,而是字符代码,那么可以调用 charCodeAt() 方法:

var oStringObject = new String("hello world");
alert(oStringObject.charCodeAt(1));	//输出 "101"

这个例子输出 "101",即小写字母 "e" 的字符代码。

concat() 方法

接下来是 concat() 方法,用于把一个或多个字符串连接到 String 对象的原始值上。该方法返回的是 String 原始值,保持原始的 String 对象不变:

var oStringObject = new String("hello ");
var sResult = oStringObject.concat("world");
alert(sResult);		//输出 "hello world"
alert(oStringObject);	//输出 "hello "

在上面这段代码中,调用 concat() 方法返回的是 "hello world",而 String 对象存放的仍然是 "hello "。出于这种原因,较常见的是用加号(+)连接字符串,因为这种形式从逻辑上表明了真正的行为:

var oStringObject = new String("hello ");
var sResult = oStringObject + "world";
alert(sResult);		//输出 "hello world"
alert(oStringObject);	//输出 "hello "

indexOf() 和 lastIndexOf() 方法

迄今为止,已讨论过连接字符串的方法,访问字符串中的单个字符的方法。不过如果无法确定在某个字符串中是否确实存在一个字符,应该调用什么方法呢?这时,可调用 indexOf() 和 lastIndexOf() 方法。

indexOf() 和 lastIndexOf() 方法返回的都是指定的子串在另一个字符串中的位置,如果没有找不到子串,则返回 -1。

这两个方法的不同之处在于,indexOf() 方法是从字符串的开头(位置 0)开始检索字符串,而 lastIndexOf() 方法则是从字符串的结尾开始检索子串。例如:

var oStringObject = new String(٤٥٬٬ٯ ٯ٬ٯ٬ٯ٥٤٥٤!);
alert(oStringObject.indexOf("o"));		//يتم عرض "4"
alert(oStringObject.lastIndexOf("o"));		//يتم عرض "7"

في هذا السياق، يظهر أول "o" النصي في الموضع 4، وهو "o" في "hello"؛ يظهر آخر "o" النصي في الموضع 7، وهو "o" في "world". إذا كان هناك نص واحد يحتوي على "o"، فإنه يعود مواضع indexOf() وlastIndexOf() نفسه.

طريقة localeCompare()

الطريقة التالية هي localeCompare()، التي تقوم بترتيب النصوص. هذه الطريقة لها معامل واحد - النص الذي سيتم مقارنته، وتعود إحدى القيم الثلاثة التالية:

  • إذا كانت String تعتمد على الترتيب الأبجدي لتنتهي قبل النص المحدد كمعامل، فإنها تعود سالبة.
  • إذا كانت String تساوي النص المحدد كمعامل، فإنها تعود 0
  • إذا كانت String تعتمد على الترتيب الأبجدي لتنتهي قبل النص المحدد كمعامل، فإنها تعود إيجابية.

ملاحظة:إذا كانت القيمة العودية سالبة، فإنها غالبًا ما تكون -1، ولكن القيمة التي تعودها تتوقف على التنفيذ. إذا كانت القيمة العودية إيجابية، فإنها غالبًا ما تكون 1، ولكن القيمة التي تعودها تتوقف على التنفيذ.

إليك مثالًا:

var oStringObject = new String("yellow");
alert(oStringObject.localeCompare("brick"));		//يتم عرض "1"
alert(oStringObject.localeCompare("yellow"));		//يتم عرض "0"
alert(oStringObject.localeCompare("zoo"));		//يتم عرض "-1"

في هذا الكود، تم مقارنة النص "yellow" مع 3 قيم، وهي "brick" و "yellow" و "zoo". بسبب ترتيب الأحرف الأبجدية، يقع "yellow" بعد "brick"، لذا يعود localeCompare() بـ 1؛ "yellow" يساوي "yellow"، لذا يعود localeCompare() بـ 0؛ "zoo" يقع بعد "yellow"، لذا يعود localeCompare() بـ -1. دعنا نكرر مرة أخرى، لأن القيمة التي تعودها تتوقف على التنفيذ، لذا من الأفضل استدعاء طريقة localeCompare() بهذه الطريقة:

var oStringObject1 = new String("الأصفر");
var oStringObject2 = new String("الطوب");
var iResult = oStringObject1.localeCompare(oStringObject2);
if(iResult < 0) {
  alert(oStringObject1 + " يأتي قبل " + oStringObject2);
}
  alert(oStringObject1 + " يأتي بعد " + oStringObject2);
}
  alert("السلسلتين متساويتين");
}

بتحقيق هذا التركيب، يمكن ضمان تشغيل هذا الكود بشكل صحيح في جميع التطبيقات.

يتميز localeCompare() بوضوح الموقع (locale، يشير أيضًا إلى البلد/المنطقة واللغة) الذي يتم فيه تنفيذ هذه الطريقة بوضوح كيفية تشغيل هذه الطريقة. في الولايات المتحدة، هي اللغة الإنجليزية هي لغة ECMAScript، localeCompare() هو تقسيم الحروف الأبجدية، حيث يأتي الحرف الكبير بعد الحرف الصغير في الترتيب. ولكن، في المناطق الأخرى، قد تكون الأمور مختلفة.

slice() و substring()

ECMAScript يقدمان طريقتين لإنشاء قيم String من النص الفرعي، هما slice() و substring(). يعود كلا الطريقتين بالنص الفرعي الذي يتم معالجته، وكل منهما تستقبل إحدى أو إثنتين من المعلمات. المعلمات الأولى هي موقع النص الفرعي الذي يتم الحصول عليه، والمعلمات الثانية (إذا تم استخدامها) هي موقع النهاية للنص الفرعي الذي يتم الحصول عليه قبل النهاية (بمعنى آخر، لا يشمل النص الفرعي النهاية في القيمة التي يتم العودة إليها). إذا تم تمرير المعلمات الثانية، يتم افتراض موقع النهاية كطول النص.

مثل concat()، لا تغير slice() و substring() قيمة String herself. إنهم فقط يعودون بالقيمة الأصلية للString، ولكنهم يحافظون على String herself.

var oStringObject = new String("hello world");
alert(oStringObject.slice("3")); // يُعرض "lo world"
alert(oStringObject.substring("3")); // يُعرض "lo world"
alert(oStringObject.slice("3", "7")); // يُعرض "lo w"
alert(oStringObject.substring("3", "7")); // يُعرض "lo w"

في هذا المثال، تكون استخدامات slice() و substring() متشابهة، وكذلك القيم التي تعود بها. عندما يكون المعامل 3 فقط، تعود كلا الطريقتين بـ "lo world"، لأن "l" الثانية في "hello" تقع في الموضع 3. وعندما يكون لدينا معاملان "3" و "7"، تعود القيم لكلا الطريقتين بـ "lo w" (يقع الحرف "o" في الموضع 7 في "world"، لذا لا يشمل الناتج)

لماذا هناك طريقتان لهما نفس الوظيفة؟ في الواقع، ليست هاتان الطريقتان متشابهتان تمامًا، ولكن يختلفان في كيفية التعامل مع المعاملات السلبية فقط.

بالنسبة للمعاملات السلبية، يستخدم method slice() إضافة المعامل إلى طول النص، بينما يتم التعامل مع substring() كمعامل 0 (بمعنى آخر، يتم تجاهله). على سبيل المثال:

var oStringObject = new String("hello world");
alert(oStringObject.slice("-3")); // يُعرض "rld"
alert(oStringObject.substring("-3")); // يُعرض "hello world"
alert(oStringObject.slice("3, -4")); // يُعرض "lo w"
alert(oStringObject.substring("3, -4")); // يُعرض "hel"

بهذا يمكن رؤية الاختلاف الرئيسي بين methods slice() و substring().

عندما يكون المعامل -3 فقط، يعود slice() بـ "rld"، ويكون substring() "hello world". هذا لأنه بالنسبة للعنصر النصي "hello world"، يتم تحويل slice("-3") إلى slice("8")، ويتم تحويل substring("-3") إلى substring("0").

同样,使用参数 3 和 -4 时,差别也很明显。slice() 将被转换成 slice(3, 7),与前面的例子相同,返回 "lo w"。而 substring() 方法则将两个参数解释为 substring(3, 0),实际上即 substring(0, 3),因为 substring() 总把较小的数字作为起始位,较大的数字作为终止位。因此,substring("3, -4") 返回的是 "hel"。这里的最后一行代码用来说明如何使用这些方法。

toLowerCase()、toLocaleLowerCase()、toUpperCase() 和 toLocaleUpperCase()

最后一套要讨论的方法涉及大小写转换。有 4 种方法用于执行大小写转换,即

  • toLowerCase()
  • toLocaleLowerCase()
  • toUpperCase()
  • toLocaleUpperCase()

从名字上可以看出它们的用途,前两种方法用于把字符串转换成全小写的,后两种方法用于把字符串转换成全大写的。

toLowerCase() 和 toUpperCase() 方法是原始的,是以 java.lang.String 中相同方法为原型实现的。

toLocaleLowerCase() 和 toLocaleUpperCase() 方法是基于特定的区域实现的(与 localeCompare() 方法相同)。在许多区域中,区域特定的方法都与通用的方法完全相同。不过,有几种语言对 Unicode 大小写转换应用了特定的规则(例如土耳其语),因此必须使用区域特定的方法才能进行正确的转换。

var oStringObject = new String(٢٬٬٬ٯ ٬ٯ٬٬٬ٯ٬ٯ٬٬ٯ);
alert(oStringObject.toLocaleUpperCase());	//输出 ٬٬٬٬ٯ ٬٬٬٬ٯ ٬٬٬٬ٯ
alert(oStringObject.toUpperCase());		//输出 ٬٬٬٬ٯ ٬٬٬٬ٯ ٬٬٬٬ٯ
alert(oStringObject.toLocaleLowerCase());	//输出 ٢٬٬٬٬ ٯ ٬ٯ٬٬٬ٯ٬ٯ٬٬ٯ
alert(oStringObject.toLowerCase());		//يخرج "hello world"

في هذا الكود، تقومtoUpperCase() وtoLocaleUpperCase() بإخراج "HELLO WORLD"، وتقومtoLowerCase() وtoLocaleLowerCase() بإخراج "hello world". عادةً، إذا لم تكن تعرف في أي تشفير يعمل لغة معينة، فإن استخدام الطرق المتعلقة بالمنطقة هو آمن.

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

عمولة instanceof

يحدث مشكلة عند استخدام عمولة typeof مع أنواع الاستدلال، حيث يعود دائمًا بـ "object"، بغض النظر عن نوع العنصر. أدخل ECMAScript عمولة أخرى instanceof لحل هذه المشكلة.

عمولة instanceof مشابهة لـ typeof، ويستخدم لتحديد نوع العنصر الذي يتم معالجته. على عكس طريقة typeof، تتطلب طريقة instanceof أن يحدد المطور بشكل صريح نوع العنصر. على سبيل المثال:

var oStringObject = new String("hello world");
alert(oStringObject instanceof String);	//يخرج "true"

هذا الكود يسأل "هل هو مثال على String في oStringObject؟" oStringObject بالفعل مثال على String، لذا النتيجة هي "true". على الرغم من أنها ليست مرنة مثل طريقة typeof، إلا أن طريقة instanceof تكون مفيدة عندما يكون typeof يعود بـ "object".