يسمح لنا بناء الجملة العادي {...}
بإنشاء كائن واحد. ولكن غالبًا ما نحتاج إلى إنشاء العديد من الكائنات المتشابهة، مثل تعدد المستخدمين أو عناصر القائمة وما إلى ذلك.
يمكن القيام بذلك باستخدام وظائف المنشئ والمشغل "new"
.
وظائف المنشئ من الناحية الفنية هي وظائف عادية. هناك اتفاقيتين على الرغم من:
يتم تسميتهم بحرف كبير أولاً.
يجب أن يتم تنفيذها فقط مع عامل التشغيل "new"
.
على سبيل المثال:
وظيفة المستخدم (الاسم) { this.name = name; this.isAdmin = false; } اسمح للمستخدم = مستخدم جديد("جاك"); تنبيه (اسم المستخدم) ؛ // جاك تنبيه (user.isAdmin)؛ // خطأ شنيع
عند تنفيذ دالة باستخدام new
، فإنها تقوم بالخطوات التالية:
يتم إنشاء كائن فارغ جديد وتعيينه this
.
ينفذ الجسم الوظيفي. عادةً ما يقوم بتعديل this
وإضافة خصائص جديدة إليه.
يتم إرجاع قيمة this
.
بمعنى آخر، new User(...)
يفعل شيئًا مثل:
وظيفة المستخدم (الاسم) { // هذا = {}; (ضمنا) // أضف خصائص إلى هذا this.name = name; this.isAdmin = false; // إرجاع هذا؛ (ضمنا) }
لذا let user = new User("Jack")
يعطي نفس النتيجة على النحو التالي:
السماح للمستخدم = { الاسم: "جاك"، المشرف: خطأ };
الآن إذا أردنا إنشاء مستخدمين آخرين، فيمكننا استدعاء new User("Ann")
، new User("Alice")
وما إلى ذلك. أقصر بكثير من استخدام القيم الحرفية في كل مرة، كما أنها سهلة القراءة.
هذا هو الغرض الرئيسي من المنشئين – تنفيذ كود إنشاء كائن قابل لإعادة الاستخدام.
دعونا نلاحظ مرة أخرى – من الناحية الفنية، يمكن استخدام أي وظيفة (باستثناء وظائف السهم، لأنها لا تحتوي على this
) كمنشئ. يمكن تشغيله باستخدام new
وسيقوم بتنفيذ الخوارزمية المذكورة أعلاه. يعد "الحرف الكبير أولاً" بمثابة اتفاقية مشتركة لتوضيح أنه سيتم تشغيل الوظيفة باستخدام new
.
وظيفة جديدة () {… }
إذا كان لدينا العديد من أسطر التعليمات البرمجية التي تدور حول إنشاء كائن معقد واحد، فيمكننا تغليفها في دالة إنشاء تسمى على الفور، مثل هذا:
// أنشئ دالة واستدعها على الفور بـ new دع المستخدم = وظيفة جديدة () { this.name = "جون"; this.isAdmin = false; // ...رمز آخر لإنشاء المستخدم // ربما منطق وعبارات معقدة // المتغيرات المحلية وما إلى ذلك };
لا يمكن استدعاء هذا المنشئ مرة أخرى، لأنه لم يتم حفظه في أي مكان، بل تم إنشاؤه واستدعاؤه فقط. لذا تهدف هذه الخدعة إلى تغليف الكود الذي يبني الكائن الوحيد، دون إعادة استخدامه في المستقبل.
الاشياء المتقدمة
نادرًا ما يتم استخدام بناء الجملة من هذا القسم، قم بتخطيه إلا إذا كنت تريد معرفة كل شيء.
داخل دالة، يمكننا التحقق مما إذا تم استدعاؤها باستخدام new
أو بدونها، وذلك باستخدام خاصية new.target
خاصة.
وهي غير محددة للمكالمات العادية وتساوي الوظيفة إذا تم استدعاؤها باستخدام new
:
وظيفة المستخدم () { تنبيه (new.target)؛ } // بدون "جديد": مستخدم()؛ // غير محدد // مع "الجديد": مستخدم جديد(); // وظيفة المستخدم {...}
يمكن استخدام ذلك داخل الدالة لمعرفة ما إذا كان قد تم استدعاؤها باستخدام new
"في الوضع المنشئ" أو بدونه "في الوضع العادي".
يمكننا أيضًا إجراء مكالمات new
ومنتظمة للقيام بنفس الشيء، مثل هذا:
وظيفة المستخدم (الاسم) { if (!new.target) { // إذا قمت بتشغيلي بدون جديد إرجاع مستخدم جديد (الاسم)؛ // ...سأضيف لك الجديد } this.name = name; } دع جون = مستخدم("جون"); // يعيد توجيه المكالمة إلى مستخدم جديد تنبيه (جون. اسم)؛ // جون
يُستخدم هذا الأسلوب أحيانًا في المكتبات لجعل بناء الجملة أكثر مرونة. حتى يتمكن الأشخاص من استدعاء الوظيفة بـ new
أو بدونها، ولا تزال تعمل.
ربما ليس من الجيد استخدامه في كل مكان، لأن حذف new
يجعل ما يحدث أقل وضوحًا. مع new
نعلم جميعًا أنه يتم إنشاء الكائن الجديد.
عادة، ليس لدى المنشئين بيان return
. مهمتهم هي كتابة كل الأشياء الضرورية في this
، وتصبح النتيجة تلقائيًا.
ولكن إذا كان هناك بيان return
، فإن القاعدة بسيطة:
إذا تم استدعاء return
مع كائن، فسيتم إرجاع الكائن بدلاً من this
.
إذا تم استدعاء return
باستخدام أمر بدائي، فسيتم تجاهله.
بمعنى آخر، return
مع كائن تعيد هذا الكائن، وفي جميع الحالات الأخرى يتم إرجاع this
.
على سبيل المثال، هنا return
يتجاوز this
عن طريق إرجاع كائن:
الدالة BigUser() { this.name = "جون"; إرجاع { الاسم: "غودزيلا" }؛ // <-- يُرجع هذا الكائن } تنبيه (new BigUser().name ); // جودزيلا، حصلت على هذا الكائن
وإليك مثالًا يحتوي على return
فارغ (أو يمكننا وضع عنصر بدائي بعده، لا يهم):
وظيفة مستخدم صغير () { this.name = "جون"; يعود؛ // <-- يُرجع هذا } تنبيه (جديد SmallUser().name ); // جون
عادة لا يكون لدى المنشئين بيان return
. نذكر هنا السلوك الخاص مع إرجاع الكائنات بشكل أساسي من أجل الاكتمال.
حذف الأقواس
بالمناسبة، يمكننا حذف الأقواس بعد new
:
السماح للمستخدم = مستخدم جديد؛ // <-- بدون أقواس // نفس السماح للمستخدم = مستخدم جديد ()؛
لا يعتبر حذف الأقواس هنا "أسلوبًا جيدًا"، لكن بناء الجملة مسموح به من خلال المواصفات.
يوفر استخدام وظائف المنشئ لإنشاء الكائنات قدرًا كبيرًا من المرونة. قد تحتوي وظيفة المنشئ على معلمات تحدد كيفية إنشاء الكائن وما يجب وضعه فيه.
وبطبيعة الحال، يمكننا أن نضيف إلى this
ليس فقط الخصائص، بل الأساليب أيضًا.
على سبيل المثال، يقوم new User(name)
أدناه بإنشاء كائن name
المحدد والطريقة sayHi
:
وظيفة المستخدم (الاسم) { this.name = name; this.sayHi = function() { تنبيه("اسمي:" + this.name ); }; } دع جون = مستخدم جديد("جون"); john.sayHi(); // اسمي: جون /* جون = { الاسم: "جون"، قل مرحبا: وظيفة () { ... } } */
لإنشاء كائنات معقدة، هناك بناء جملة أكثر تقدمًا، وهو الفئات، التي سنغطيها لاحقًا.
وظائف المنشئ، أو باختصار، المنشئات، هي وظائف عادية، ولكن هناك اتفاق مشترك على تسميتها بالحرف الكبير أولاً.
يجب استدعاء وظائف المُنشئ فقط باستخدام new
. مثل هذا الاستدعاء يعني إنشاء this
فارغًا في البداية وإرجاع المأهول في النهاية.
يمكننا استخدام وظائف البناء لإنشاء كائنات متعددة متشابهة.
توفر JavaScript وظائف منشئة للعديد من كائنات اللغة المضمنة: مثل Date
للتواريخ، و Set
للمجموعات وغيرها التي نخطط لدراستها.
الأشياء، سوف نعود!
في هذا الفصل نغطي فقط الأساسيات المتعلقة بالأشياء والمنشئات. وهي ضرورية لمعرفة المزيد عن أنواع البيانات ووظائفها في الفصول التالية.
بعد أن نتعلم ذلك، نعود إلى الأشياء ونغطيها بعمق في فصول النماذج الأولية والميراث والفئات.
الأهمية: 2
هل من الممكن إنشاء وظائف A
و B
بحيث يكون new A() == new B()
؟
الدالة أ () { ... } الدالة ب () { ... } دع a = جديد A(); دع ب = جديد ب()؛ تنبيه (أ == ب)؛ // حقيقي
إذا كان الأمر كذلك، فقم بتقديم مثال على الكود الخاص بهم.
نعم، هذا ممكن.
إذا قامت دالة بإرجاع كائن ما، فإن new
ترجعه بدلاً من this
.
لذا يمكنهم، على سبيل المثال، إرجاع نفس الكائن المحدد خارجيًا obj
:
دع obj = {}; الوظيفة أ () {إرجاع الكائن؛ } وظيفة B () {إرجاع الكائن؛ } تنبيه (جديد A () == جديد B ())؛ // حقيقي
الأهمية: 5
قم بإنشاء Calculator
دالة منشئة تقوم بإنشاء كائنات بثلاث طرق:
تطالب الدالة read()
بقيمتين وتحفظهما كخصائص كائن بالاسمين a
و b
على التوالي.
تُرجع الدالة sum()
مجموع هذه الخصائص.
تقوم mul()
بإرجاع حاصل ضرب هذه الخصائص.
على سبيل المثال:
دع الآلة الحاسبة = الحاسبة الجديدة () ؛ آلة حاسبة. قراءة ()؛ تنبيه("Sum=" + حاسبة.sum() ); تنبيه ("Mul = " + حاسبة.mul ())؛
قم بتشغيل العرض التوضيحي
افتح صندوق الرمل مع الاختبارات.
حاسبة الدالة () { هذا.قراءة = وظيفة () { this.a = +prompt('a?', 0); this.b = +prompt('b?', 0); }; هذا.مجموع = وظيفة () { إرجاع this.a + this.b; }; هذا.مول = وظيفة() { إرجاع this.a * this.b; }; } دع الآلة الحاسبة = الحاسبة الجديدة () ؛ آلة حاسبة. قراءة ()؛ تنبيه("Sum=" + حاسبة.sum() ); تنبيه ("Mul = " + حاسبة.mul ())؛
افتح الحل بالاختبارات في وضع الحماية.
الأهمية: 5
قم بإنشاء دالة منشئة Accumulator(startingValue)
.
يجب أن يكون الكائن الذي يقوم بإنشائه:
قم بتخزين "القيمة الحالية" في value
العقار. يتم تعيين قيمة البداية على وسيطة المنشئ startingValue
.
يجب أن تستخدم طريقة read()
prompt
لقراءة رقم جديد وإضافته إلى value
.
بمعنى آخر، الخاصية value
هي مجموع كل القيم التي أدخلها المستخدم بالقيمة الأولية startingValue
.
إليك العرض التوضيحي للكود:
دع المجمع = تراكم جديد (1)؛ // القيمة الأولية 1 تراكم. قراءة ()؛ // يضيف القيمة التي أدخلها المستخدم تراكم. قراءة ()؛ // يضيف القيمة التي أدخلها المستخدم تنبيه (تراكم. قيمة)؛ // يظهر مجموع هذه القيم
قم بتشغيل العرض التوضيحي
افتح صندوق الرمل مع الاختبارات.
وظيفة تراكم (قيمة البداية) { this.value = startValue; هذا.قراءة = وظيفة () { this.value += +prompt('ما المبلغ الذي يجب إضافته؟', 0); }; } دع المجمع = تراكم جديد (1)؛ تراكم. قراءة ()؛ تراكم. قراءة ()؛ تنبيه (تراكم. قيمة)؛
افتح الحل بالاختبارات في وضع الحماية.