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

على مر السنين ، قمت ببناء نموذج جافا سكريبت العقلي الذي يعطيني شعور بالثقة. أنا هنا سأشارككم نسخة موجزة للغاية من هذا النموذج. هيكلها يشبه القاموس. يوصف كل مفهوم في عدة جمل.
عندما تقرأ هذه المادة ، حاول أن تقيم عقلياً مدى ثقتك في كل قضية تمت مناقشتها هنا. وإذا اتضح أن الكثير من الأشياء من هنا تبدو غير مألوفة لك ، فلن ألومك على ذلك. ولكن إذا كان هذا صحيحًا ، فهناك شيء ما في نهاية المادة يساعدك في تصحيح الموقف.
نموذج جافا سكريبت العقلي
- قيمة. مفهوم المعنى مجردة بعض الشيء. إنه "شيء ما". القيمة في JavaScript هي نفس رقم الرياضيات ، أو نقطة في الهندسة. عند تشغيل البرنامج ، فإن عالم هذا البرنامج مليء بالمعاني. الأرقام مثل
1
و 2
و 420
هي قيم. لكن المعاني هي كيانات أخرى. على سبيل المثال ، الجملة "Cows go moo"
. صحيح ، ليس كل شيء هو المعنى. الرقم هو قيمة ، لكن عبارة if
لم تعد قيمة. أدناه سنتحدث عن أنواع مختلفة من القيم.
- نوع القيمة. هناك أنواع مختلفة من القيم. على سبيل المثال ، الأرقام - مثل
420
، سلاسل - مثل "Cows go moo"
، كائنات. هناك أنواع أخرى من القيم. يمكنك معرفة نوع القيمة باستخدام مشغل typeof
. على سبيل المثال ، فإن command console.log(typeof 2)
سوف يخرج number
إلى وحدة التحكم. - القيم البدائية. بعض القيم لها أنواع "بدائية". هذه هي الأرقام والسلاسل وبعض المعاني الأخرى. خاصية واحدة مثيرة للاهتمام من القيم البدائية هي أنه لا يمكنك إنشاء مثل هذه القيم أكثر مما هو موجود في اللغة ، لا يمكنك تغيير القيم البدائية الموجودة. على سبيل المثال ، في كل مرة تستخدم فيها الرقم
2
في الكود ، ستكون نفس القيمة 2
. من المستحيل "إنشاء" قيمة أخرى واحدة في البرنامج ، أو تحويل "تحول" إلى 3
. هذا صحيح أيضا للسلاسل. - القيم
null
وغير undefined
. هذان معاني خاصة. إنهم ليسوا مثل الآخرين ، نظرًا لحقيقة أنه لا يمكن القيام بالكثير من الأشياء معهم - وغالبًا ما يؤدي ظهورهم إلى أخطاء. عادةً ما يكون استخدام null
عبارة عن إشارة إلى أن بعض القيمة لم يتم تعيينها إلى متغير عن قصد ، ويشير undefined
إلى أن بعض القيمة مفقودة عن طريق الصدفة. ومع ذلك ، يقرر مبرمج كيفية استخدام هذه القيم بالضبط. توجد هذه القيم بسبب حقيقة أنه من الأفضل في بعض الأحيان حدوث خطأ أثناء تنفيذ عملية معينة ، ولن يحدث أن يستمر تنفيذ البرنامج بعد "معالجة" قيمة غير موجودة.
- المساواة. مثل مفهوم المعنى ، فإن مفهوم المساواة هو أحد المفاهيم الأساسية لجافا سكريبت. نحن نقول أن هناك قيمتين متساويتين إذا ... في الواقع ، لن أقول ذلك. إذا كانت قيمتان متساويتين ، فهذا يعني أنهما نفس القيمة. ليس هناك معنيان مختلفان ، لكن واحد! على سبيل المثال ، المساواة
"Cows go moo" === "Cows go moo"
و 2 === 2
صحيحة. وهنا كل شيء واضح: 2
هو 2
. يرجى ملاحظة أننا نستخدم ثلاث علامات متساوية ، والتي تمثل مفهوم المساواة في القيم أعلاه في JavaScript.
- المساواة الصارمة. تحدثنا للتو عنه في الفقرة السابقة.
- المساواة في الروابط. وتحدثنا عنه فقط.
- مساواة غير متساوية. أوه ، لكن هذا شيء مختلف تمامًا. في JavaScript ، يتم تنفيذ التحقق من عدم المساواة الصارمة في القيم باستخدام عامل تشغيل يتكون من علامتين متساويتين (
==
). يمكن التعرف على الكيانات على قدم المساواة مع بعضها البعض حتى لو كانت ممثلة بمعاني مختلفة تشبه بعضها البعض (شيء مثل 2
و "2"
). تمت إضافة مشغل مساواة غير صارم لجافا سكريبت في المراحل الأولى من تطوير اللغة ، للراحة. منذ ذلك الحين ، كان مصدرا لا لبس فيه من الارتباك. لا يمكن اعتبار مفهوم المساواة الفضفاضة أساسيا ، لكنه مصدر نموذجي للأخطاء. يمكنك معرفة عامل المساواة غير الصارم في يوم ممطر ، لكن الكثير منهم ببساطة يحاولون عدم استخدام العامل ==
.
- الحرفي. يتم استخدام القيم الحرفية عند الرجوع إلى القيمة عن طريق كتابتها إلى رمز البرنامج. على سبيل المثال ،
2
عبارة عن حرفية رقمية ، و "Banana"
عبارة عن سلسلة حرفية. - المتغير. تتيح لك المتغيرات الرجوع إلى القيم باستخدام الأسماء. على سبيل المثال ،
let message = "Cows go moo"
. بعد استخدام بنية مشابهة في التعليمات البرمجية ، أينما كنت بحاجة إلى جملة "Cows go moo"
، يمكنك كتابة message
فقط ، بدلاً من تكرار هذه الجملة. في وقت لاحق ، يمكنك تغيير message
بجعل النقطة المتغيرة إلى شيء آخر. على سبيل المثال ، باستخدام هذا البناء: message = "I am the walrus"
. يرجى ملاحظة أن هذا لا يغير المعنى نفسه. هذا يؤثر فقط على ما يشير المتغير. يشبه "توصيل" اسم متغير بشيء آخر. في البداية ، تم توصيل المتغير بـ "Cows go moo"
، والآن إلى "I am the walrus"
.
- نطاق المتغير. إذا كان يمكن استخدام متغير واحد فقط مع
message
الاسم في البرنامج بأكمله ، فسيكون ذلك سيئًا للغاية. عندما نعلن متغير ، فهو متاح فقط في جزء من البرنامج. يسمى هذا الجزء "نطاق المتغير". هناك قواعد تصف ميزات النطاق. يمكنك عادة تحديد نطاق المتغير من خلال معرفة الكتلة التي تحدها الأقواس المتعرجة ( {}
) يتم الإعلان عنها. ويمكن أيضا أن تسمى هذه الكتلة نطاق المتغير. - تعيين القيم للمتغيرات. عندما نكتب
message = "I am the walrus"
في الكود ، يؤدي هذا إلى حقيقة أننا نغير متغير message
بحيث يشير إلى القيمة "I am the walrus"
. تسمى هذه العملية تعيين متغير لقيمة ، أو كتابة شيء لمتغير ، أو تعيين متغير. - الكلمات الرئيسية
let
، const
و var
. بشكل عام ، let
هي أفضل كلمة رئيسية لإعلان المتغيرات. إذا كنت تريد التأكد من أنه لا يمكن كتابة شيء جديد في متغير ، يمكنك استخدام الكلمة الأساسية const
. (بعض قواعد التعليمات البرمجية والأوامر غير متحيزة حول هذه المشكلة ، مما يضطر الجميع ، إذا كانت القيمة مكتوبة إلى المتغير مرة واحدة فقط ، استخدم const
.) حاول عدم استخدام الكلمة الرئيسية var
، لأنه مع المتغيرات المعلنة معها ، القواعد ذات الصلة المتعلقة بتعريف نطاق المتغيرات.
- اكتب
Object
. يلعب نوع Object
، الكيانات التي تسمى الكائنات ، دورًا خاصًا في JavaScript. من السمات البارزة للكائنات أنه يمكن ربطها بقيم أخرى. على سبيل المثال ، يحتوي كائن {flavor: "vanilla"}
على خاصية flavor
تشير إلى قيمة "vanilla"
. يمكن اعتبار الكائنات كقيم مستقلة ، يتم من خلالها رسم ارتباطات بالقيم الأخرى.
- خاصية الكائن. الخاصية تشبه "الاتصال" الذي يأتي من كائن ويشير إلى قيمة معينة. قد يذكرك هذا بفكرة المتغير: الخاصية لها اسم (مثل
flavor
) ، فهي تشير إلى قيمة (مثل "vanilla"
). ولكن ، على عكس المتغير ، فإن الخصائص "تعيش" داخل الكائن نفسه ، وليس في مكان ما في الكود (في نطاق معين من المتغير). تعتبر الخاصية جزءًا من الكائن ، ولا تعتبر القيمة المشار إليها بواسطة الخاصية جزءًا من الكائن. - كائن الحرفي. الكائن الحرفي هو آلية تسمح لك بإنشاء كائنات عن طريق إدخال الإنشاءات المناسبة في التعليمات البرمجية. على سبيل المثال ، هذا
{}
أو {flavor: "vanilla"}
. في الأقواس المعقوفة ، يمكن التصريح عن العديد من أزواج :
النموذج :
، مفصولة بفواصل. هذا يسمح لنا بتحديد القيم المشار إليها بواسطة خصائص الكائنات. - هوية الأشياء. لقد سبق أن قلنا أن الرقم
2
يساوي 2
(بمعنى آخر - 2 === 2
) ، لأنه حيثما نكتب الرقم 2
، فإننا "ندعو" بنفس القيمة إلى هذا المكان. لكن في كل مرة نكتب فيها {}
، نحصل دائمًا على قيم مختلفة. نتيجة لذلك ، لا يعد أحد كائنات النموذج {}
مساويا لكائن آخر ، والذي يشبه أيضًا {}
. حاول كتابة ما يلي في وحدة التحكم: {} === {}
(ستكون النتيجة false
). عندما يصادف الكمبيوتر الرقم 2
في الكود ، فإنه يعمل دائمًا بنفس الشيطان. لكن حرفية الكائنات هي شيء آخر. عندما يصادف الكمبيوتر {}
، فإنه ينشئ كائنًا جديدًا ، وهو دائمًا القيمة الجديدة. كيفية التحقق من الكائنات من أجل المساواة؟ يمكن اعتبار مفهوم "المساواة" مفهوم "هوية القيم". عندما نقول: " a
و b
متطابقان" - هذا يعني أننا نعني أن a
و b
يشيران إلى نفس القيمة ( a === b
). عندما نقول أن a
و b
غير متطابقتين ، فهذا يعني أن a
و b
يشيران إلى قيم مختلفة (أي ، a !== b
). - تدوين نقطة. عندما تحتاج إلى قراءة قيمة خاصية لكائن ما أو كتابة شيء ما إلى خاصية ما ، يمكنك استخدام علامة النقطة (
.
). على سبيل المثال ، إذا كان المتغير iceCream
يشير إلى كائن يحتوي flavor
ممتلكاته على السلسلة "chocolate"
، فإن بناء iceCream.flavor
سيعطينا "chocolate"
. - ترميز القوس. في بعض الأحيان ، اسم خاصية الكائن المراد معالجتها غير معروف مقدمًا. على سبيل المثال ، في بعض الأحيان تحتاج إلى قراءة قيمة خاصية
iceCream.flavor
، وفي بعض الأحيان تحتاج إلى قراءة قيمة خاصية iceCream.flavor
. يتيح لك تدوين الأقواس ( []
) الوصول إلى خصائص الكائنات عن طريق تعيين أسمائهم باستخدام المتغيرات. على سبيل المثال ، افترض وجود مثل هذا المتغير في الكود: let ourProperty = 'flavor'
. هذا يعني أن التصميم مثل iceCream[ourProperty]
سيمنحنا قيمة "chocolate"
. ومن المثير للاهتمام ، يمكنك استخدام تدوين الأقواس عند إنشاء كائنات: { [ourProperty]: "vanilla" }
. - الطفرة. نحن نتحدث عن حقيقة أن كائن يتحور (أو يتغير) إذا كتب شخص ما قيمة جديدة لخاصيته. على سبيل المثال ، إذا أنشأنا كائنًا ،
let iceCream = {flavor: "vanilla"}
، فيما بعد يمكننا تعيين قيمة جديدة للخاصية باستخدام iceCream.flavor = "chocolate"
. يرجى ملاحظة أنه حتى إذا أعلنا استخدام iceCream
المتغير باستخدام الكلمة الأساسية const
، فلن يمنعنا ذلك من تغيير خاصية الكائن iceCream.flavor
. هذا لأن استخدام const
يحمي فقط المتغير iceCream
من الكتابة فوقه ، ونقوم بتغيير خاصية flavor
الكائن المشار إليه بواسطة المتغير. رفض بعض الأشخاص استخدام const
فقط لأن هذه الكلمة الرئيسية قادرة على تضليل المبرمج. - مجموعة. الصفيف هو كائن عبارة عن مجموعة من قيم معينة. يمكن الإعلان عن المصفوفات باستخدام القيم الحرفية للمصفوفة ، على سبيل المثال ، مثل هذا:
["banana", "chocolate", "vanilla"]
. يؤدي استخدام مثل هذا الإنشاء إلى إنشاء كائن تشير ممتلكاته التي تحمل الاسم 0
إلى السلسلة "banana"
، والخاصية 1
- إلى السلسلة "chocolate"
، والملكية 2
- إلى قيمة "vanilla"
. سيكون من الممل كتابة نفس الشيء مثل هذا: {0: ..., 1: ..., 2: ...}
. لذلك ، المصفوفات هي هياكل مفيدة. تحتوي المصفوفات على آليات مدمجة مصممة للعمل مع عناصرها. من بينها map
، filter
reduce
الأساليب. لا تحبط إذا كان الاسم المختزل يبدو مربكًا لك. يبدو غير مفهومة للجميع. - النموذج. ماذا يحدث إذا حاولت الوصول إلى كائن غير موجود؟ على سبيل المثال ، ماذا يحدث إذا وصلنا إلى
iceCream.taste
وكان الكائن يحتوي على خاصية flavor
فقط؟ إذا أجبنا على هذا السؤال دون الخوض في التفاصيل ، فيمكننا القول أنه إذا حاولنا اللجوء إلى خاصية غير موجودة ، فإننا نحصل على قيمة خاصة undefined
. إذا قدمت إجابة مفصلة على هذا السؤال ، فعليك أن تبدأ بحقيقة أن معظم الكائنات في جافا سكريبت لديها ما يسمى "النموذج الأولي". يمكن اعتبار النموذج الأولي لكائن كخاصية "مخفية" تخبر النظام بمكان البحث عن الخاصية المطلوبة إذا لم تكن موجودة في الكائن نفسه. في مثالنا ، عندما يتضح أن كائن iceCream
يحتوي على خاصية taste
، سيبحث JavaScript عن هذه الخاصية في النموذج الأولي للكائن ، وهو أيضًا كائن. وإذا لم يجدها هناك ، فعندئذٍ في النموذج الأولي للنموذج ، وما إلى ذلك. سيتم .taste
قيمة undefined
فقط عند الوصول إلى نهاية سلسلة النموذج الأولي ، ولم يتم العثور على خاصية .taste
. نادراً ما يتعين عليك العمل مباشرة مع هذه الآلية ، لكن مع العلم iceCream
الأولية ، يمكنك أن تفهم لماذا iceCream
كائن iceCream
على طريقة toString
لم نعلن عنها مطلقًا. هذه الطريقة مأخوذة من النموذج الأولي للكائن.
- وظيفة. الوظيفة هي معنى خاص موجود لغرض وحيد هو تمثيل جزء من رمز البرنامج. الوظائف مريحة في الحالات التي لا يرغب فيها المبرمج في كتابة نفس الكود باستمرار. "المكالمة" إلى وظيفة تبدو وكأنها
sayHi()
تخبر الكمبيوتر أنه يحتاج إلى تنفيذ التعليمات البرمجية داخل الوظيفة ، ثم العودة إلى المكان الذي تم استدعاء الوظيفة فيه. يحتوي JavaScript على العديد من الطرق للإعلان عن الوظائف المختلفة قليلاً.
- وسيطات (أو معلمات) للدالة. تتيح لك الوسائط تمرير بيانات معينة إلى الوظيفة من المكان الذي يتم استدعاء الوظيفة فيه. على سبيل المثال ، قد يبدو كالتالي:
sayHi("Amelie")
. يشبه سلوك الوسائط في دالة ما سلوك المتغيرات. يتم استخدام الكلمات "المعلمات" و "الحجج" اعتمادًا على ما تتم مناقشته بالضبط - حول الإعلان عن وظيفة ، أو حول نداءها. على الرغم من أن الاختلاف في المصطلحات دقيق - في الممارسة العملية ، يتم استخدام هذه المصطلحات بالتبادل. - التعبير الوظيفي. في وقت سابق كتبنا قيم السلسلة إلى متغيرات. على سبيل المثال ،
let message = "I am the walrus"
. كما اتضح ، يمكن أيضًا كتابة دالة في متغير: let sayHi = function() { }
. ما يأتي بعد علامة =
يسمى التعبير الوظيفي. إنه يعطينا معنى خاص (وظيفة) ، وهو جزء من الكود. إذا كنا بحاجة إلى تنفيذ هذا الرمز ، فيمكننا استدعاء الوظيفة المقابلة. - إعلان وظيفة. قد يتعب أحد المبرمجين من الكتابة بشكل مستمر مثل:
let sayHi = function() { }
. إذا كان الأمر كذلك ، فيمكن استخدام نموذج أقصر لوصف الوظيفة هنا: function sayHi() { }
. هذا البناء يسمى إعلان الوظيفة. بدلاً من تحديد اسم متغير على الجانب الأيسر من التعبير ، نضع هذا الاسم بعد الكلمة function
. عادةً ما يكون النمطان لإنشاء الدالات الموضحة أعلاه قابلين للتبادل. - رفع الوظائف إلى أعلى النطاق. عادةً ما لا يمكن استخدام المتغير إلا بعد إعلانه باستخدام
let
أو const
، أسفل مكان إعلانه. في حالة الوظائف ، قد يكون هذا غير مريح. وظائف يمكن الاتصال ببعضهم البعض. قد يكون اكتشاف المهمة التي يجب إنشاؤها أولاً مهمة شاقة. الشيء الجيد هو أنه عند استخدام تعريفات الوظائف (وفقط عند استخدام هذه الطريقة!) ، فإن الترتيب الذي يتم به وصف الوظائف ليس مهمًا. والحقيقة هي أنه مع هذا النهج ، وظائف "ترتفع" إلى الجزء العلوي من النطاق. وهذا يعني أن الوظائف ، حتى عندما تحاول استدعاءها من الكود الذي يأتي قبل إعلانها ، محددة بالفعل وجاهزة للعمل. - هذه الكلمة الرئيسية. ولعل الكلمة الأساسية
this
هي مفهوم جافا سكريبت يتم فهمه غالبًا. يمكن مقارنة هذه الكلمة الأساسية بحجة دالة خاصة. لكننا نحن أنفسنا لا ننقل وظائفها. جافا سكريبت يمر بها. تعتمد قيمة this
على كيفية استدعاء الدالة. على سبيل المثال ، عند استدعاء طريقة كائن باستخدام تدوين النقاط ، مثل iceCream.eat()
، سيشير this
إلى ما أمام النقطة. في مثالنا ، هذا كائن iceCream
. تعتمد قيمة this
في دالة ما على كيفية استدعاء الوظيفة ، وليس على مكان الإعلان عنها. هناك طرق خاصة ، مثل .bind
و .apply
و .apply
، والتي تمنح المبرمج القدرة على التحكم في ما يحصل في this
. - وظائف السهم. وظائف السهم تشبه التعبيرات الوظيفية. يتم الإعلان عن مثل هذا:
let sayHi = () => { }
. فهي مدمجة وغالبًا ما تستخدم في التصاميم ذات الخط الواحد. قدرات وظائف السهم محدودة أكثر من قدرات الوظائف التقليدية. على سبيل المثال ، ليس لديهم الكلمة this
. عند استخدام this
الكلمة الأساسية في دالة سهم ، يتم أخذها من الوظيفة التي يتم تضمين وظيفة السهم فيها. يشبه هذا استدعاء وسيطة أو متغير من دالة متداخلة في دالة أخرى. في الممارسة العملية ، هذا يعني أن وظائف السهم تستخدم عندما يريدون أن تكون this
القيمة الموجودة في الكود المحيط بها مرئية لهم. - ربط
this
القيمة بالوظائف. عادةً ما يعني ربط دالة معينة f
بقيمة محددة من this
ومجموعة معينة من الوسائط أنه يتم إنشاء وظيفة جديدة تستدعي الدالة f
بهذه القيم المحددة مسبقًا. يحتوي JavaScript على آلية إضافية لوظائف الربط - طريقة .bind
، ولكن يمكنك ربط this
بالوظائف بطرق أخرى. كان التجليد طريقة شائعة للحصول على الدوال المتداخلة "لرؤية" نفس this
القيمة مثل الدوال الخارجية لها. الآن ، يتم استخدام وظائف السهم في موقف مماثل ، ونتيجة لذلك ، يتم استخدام ربط الوظائف بشكل غير منتظم في عصرنا. - استدعاء المكدس استدعاء وظيفة يشبه دخول الغرفة. في كل مرة نسميها دالة ، تتم تهيئة المتغيرات بداخلها مرة أخرى. ونتيجة لذلك ، فإن كل مكالمة وظيفية تشبه بناء "غرفة" جديدة برمز دالة. عندما يتم "بناء" الغرفة ، يتم "إدخالها" فيها ، يتم تنفيذ رمز الوظيفة. أعلنت المتغيرات في وظيفة "العيش" في هذه "الغرفة". عندما يتم إجراء العودة من وظيفة ، فإن "الغرفة" تختفي مع كل محتوياتها. يمكن تمثيل كل هذه "الغرف" التي تم إنشاؤها بواسطة المكالمات الوظيفية على أنها "برج" عالي. هذا مكدس مكالمة. عندما نخرج من وظيفة معينة ، نصل إلى الوظيفة ، التي تقع "أسفل" في مكدس الاستدعاء.
- العودية. العودية عند استدعاء دالة نفسها. هذه التقنية مفيدة في الحالات التي يلزم فيها تكرار ما تم بالفعل بواسطة الوظيفة ، ولكن باستخدام وسائط أخرى. على سبيل المثال ، إذا
collectLinks(url)
محرك بحث يبحث في مواقع الويب ، فقد تكون لدينا collectLinks(url)
. تقوم هذه الوظيفة أولاً بجمع الارتباطات الموجودة على صفحة الموقع ، ثم تقوم بالاتصال بنفسها ، لتمرير كل ارتباط من الروابط الموجودة به. , . , , , . , , stack overflow
. - , . - . — , , . , , — . — , — , , . , .
- . () — , JavaScript. , , . : . . ,
setTimeout
, … -. , . — . « », , . - . , , , , . - , . ? - . — . . , - . JavaScript, , . «». JavaScript, , , , .
JavaScript , . . JavaScript. , . JavaScript. —
Just JavaScript . , , JavaScript.
! JavaScript?
