مقدمة
لفهم مفهوم وظائف المصنع والمنشئين، يجب عليك أولاً فهم الوظائف والأشياء.
إذا أنشأتَ العديد من الكائنات ذات الخصائص والوظائف المتشابهة، فقد يصبح الأمر مملًا ومتكررًا. نودُّ أن نضع في اعتبارنا مبدأ DRY code، وهو اختصار لعبارة "لا تكرر نفسك". هناك أنماط وظيفية تُساعدنا على كتابة أكواد أقصر وأدق وأكثر كفاءة. دوال المصنع ودوال المُنشئ قادرة على أداء المهمة، ولكن أيُّها أنسب؟ لنتعمق أكثر في ماهية دوال المصنع والمنشئ، وما يُمكنها وما لا يُمكنها فعله، وأوجه التشابه والاختلاف بينهما.
ما هي وظيفة المصنع؟
يمكن اعتبار دالة المصنع مصنعًا حقيقيًا يستقبل المواد الخام ويُنتج منتجات متعددة بسرعة. أما دوال المصنع، فتستقبل مُدخلات مُحددة وتستخدمها لإنشاء كائن جديد. فكيف يُمكن أن يكون هذا مفيدًا لنا؟ يُمكننا ببساطة إنشاء كل كائن على حدة، ولكن قد يستغرق الأمر بعض الوقت. إذا كنت تُنشئ كائنات بنفس الخصائص وقيم مختلفة، فإن إنشاء دالة مصنع يُمكن أن يُسرّع العملية.
const car1 = {
make: 'Toyota',
model: 'Tacoma',
year: 2018,
fuelType: 'gas',
bodyType: 'mid-size pick-up truck',
getFullName() {
return `${this.year} ${this.make} ${this.model}`;
}
}
console.log(car1.getFullName()); // => 2018 Toyota Tacomaفي المثال السابق، أنشأنا كائنًا يصف جهازًا محددًا. الآن، لننشئ كائنًا مشابهًا لهذا.
const car2 = {
make: 'Tesla',
model: 'Model S',
year: 2018,
fuelType: 'electric',
bodyType: 'sedan',
getFullName() {
return `${this.year} ${this.make} ${this.model}`;
}
}
console.log(car2.getFullName()); // => 2018 Tesla Model S حسنًا، يمكنني الاستمرار في الحديث عن صنع المزيد من الآلات، ولكن من لديه الوقت لذلك؟ لنرَ كيف يعمل هذا كدالة مصنعية.
function createCar (make, model, year, fuelType, bodyType) {
return {
make: make,
model: model,
year: year,
fuelType: fuelType,
bodyType: bodyType,
getFullName() {
return `${year} ${make} ${model}`;
}
}
}لدينا الآن دالة مصنع تُنشئ كائنات جديدة. كل ما علينا فعله الآن هو تمرير البيانات وترك دالة المصنع تؤدي وظيفتها.
function createCar (make, model, year, fuelType, bodyType) {
return {
make: make,
model: model,
year: year,
fuelType: fuelType,
bodyType: bodyType,
getFullName() {
return `${year} ${make} ${model}`;
}
}
}
const car1 = createCar('Toyota', 'Tacoma', 2018, 'gas', 'mid-size pick-up truck');
const car2 = createCar('Tesla', 'Model S', 2018, 'electric', 'sedan');
console.log(car1.getFullName()); // => 2018 Toyota Tacoma
console.log(car2.getFullName()); // => 2018 Tesla Model Sيمكنك إنشاء أي عدد من الكائنات باستخدام وظيفة المصنع بدلاً من تكرار التعليمات البرمجية.
ما هي المنشئات؟
دالة البناء هي نمط جافا سكريبت آخر يُشبه إلى حد كبير دوال المصنع. ومع ذلك، على عكس دوال المصنع، لا تُرجع دوال البناء كائنًا فعليًا. لإنشاء كائنات مختلفة بنفس الخصائص، نحتاج إلى استخدام الكلمتين المفتاحيتين "new" و"this". بعد ذلك، لنرَ كيف تعمل دوال البناء بصريًا.
function Car(make, model, year, fuelType, bodyType) {
this.make = make
this.model = model
this.year = year
this.fuelType = fuelType
this.bodyType = bodyType
this.getFullName = () => {
return `${this.year} ${this.make} ${this.model}`;
}
}في المثال أعلاه، تشبه دالة البناء دالة المصنع إلى حد كبير، باستثناء استخدام الكلمة المفتاحية "this". تشير "this" إلى دالة البناء التي أنشأت كائن المثيل. بمعنى آخر، لا قيمة لـ "this" في دالة البناء. يمكنك اعتبارها أساسًا للكائن الجديد.
function Car(make, model, year, fuelType, bodyType) {
this.make = make
this.model = model
this.year = year
this.fuelType = fuelType
this.bodyType = bodyType
this.getFullName = () => {
return `${this.year} ${this.make} ${this.model}`;
}
}
const car1 = new car('Toyota', 'Tacoma', 2018, 'gas', 'mid-size pick-up truck');
const car2 = new car('Tesla', 'Model S', 2018, 'electric', 'sedan');
console.log(car1.getFullName()); // => 2018 Toyota Tacoma
console.log(car2.getFullName()); // => 2018 Tesla Model Sلإنشاء كائنات باستخدام دوال البناء، نستخدم كلمة مفتاحية أخرى تُسمى "جديد". عند استخدام عبارة "جديد" قبل استدعاء دالة، يقوم جافا سكريبت تلقائيًا بأمرين: داخل الدالة، يُنشئ كائنًا فارغًا يُسمى "هذا". يُرجع هذا الكائن إلى العبارة التي استدعت الدالة أصلًا.
function Car(make, model, year, fuelType, bodyType) {
// const this = {};
this.make = make
this.model = model
this.year = year
this.fuelType = fuelType
this.bodyType = bodyType
this.getFullName = () => {
return `${this.year} ${this.make} ${this.model}`;
}
// return this;
}
const car1 = new car('Toyota', 'Tacoma', 2018, 'gas', 'mid-size pick-up truck');
const car2 = new car('Tesla', 'Model S', 2018, 'electric', 'sedan');
console.log(car1.getFullName()); // => 2018 Toyota Tacoma
console.log(car2.getFullName()); // => 2018 Tesla Model Sالميراث
يلعب الميراث دورًا مهمًا في الفرق بين وظيفة المصنع ووظيفة البناء.
function createCar (make, model, year, fuelType, bodyType) {
return {
make: make,
model: model,
year: year,
fuelType: fuelType,
bodyType: bodyType,
getFullName() {
return `${year} ${make} ${model}`;
}
}
}
const car1 = createCar('Toyota', 'Tacoma', 2018, 'gas', 'mid-size pick-up truck');
const car2 = createCar('Tesla', 'Model S', 2018, 'electric', 'sedan');
car1.getFullName = function() {
return `My ${fuelType} ${bodyType} is a ${year} ${make} ${model}`;
}
console.log(car1.getFullName()); // => My gas mid-size pick-up truck is a 2018 Toyota Tacoma
console.log(car2.getFullName()); // => 2018 Tesla Model Sلنعد إلى المثال الأول لدالة المصنع. ماذا لو أردنا إعادة تعريف دالة car1.getFullName()؟ حسنًا، دالة car1.getFullName() ودالة car2.getFullName() ليستا نفس الدالة في الذاكرة. يحصل كل كائن على نسخة خاصة به من الدالة. هذا يعني أنه عندما تُنشئ الدالة كائنًا وتُرجعه، فإنها تنسخ خصائصه وقيمه وتربطها بكل كائن يستدعي الدالة.
function car(make, model, year, fuelType, bodyType) {
// const this = {};
this.make = make
this.model = model
this.year = year
this.fuelType = fuelType
this.bodyType = bodyType
this.getFullName = () => {
return `${this.year} ${this.make} ${this.model}`;
}
// return this;
}
const car1 = new car('Toyota', 'Tacoma', 2018, 'gas', 'mid-size pick-up truck');
const car2 = new car('Tesla', 'Model S', 2018, 'electric', 'sedan');
console.log(car1); // => car {make: 'Toyota', model: 'Tacoma' , etc.}لنلقِ نظرة الآن على دالة المنشئ أعلاه. عند إنشاء المنشئ، يكون له نموذج أولي خاص به. عند إنشاء كائن سيارة جديد باستخدام الكلمة المفتاحية "new"، يُنشئ مثيلًا من نوع السيارة. بمعنى آخر، يكون النموذج الأولي لـ car1 من نوع السيارة. الآن، يرث car1 من منشئ السيارة، مما يسمح لنا بإضافة خصائص إلى نموذج السيارة الأولي.
Car.prototype.sentence = function() {
return `My ${this.fuelType} ${this.bodyType} is a ${this.year} ${this.make} ${this.model}`;
}console.log(car1); // => Car {
// make: 'Toyota',
// model: 'Tacoma',
// year: 2018,
// fuelType: 'gas',
// bodyType: 'mid-size pick-up truck',
// getFullName: [Function (anonymous)]
// }لاحظ أن وظيفة الجملة لا تتم إضافتها مباشرة إلى منشئ السيارة نفسه.
console.log(Car.prototype); // => { sentence: [Function (anonymous)] }
ولكن عندما نتحقق من النموذج الأولي، نجده! يمكننا الآن الوصول إلى الوظيفة المضافة حديثًا.
console.log(car1.sentence()); // => My gas mid-size pick-up truck is a 2018 Toyota Tacoma
console.log(car2.sentence()); // => My electric sedan is a 2018 Tesla Model Sالآن وقد عرفنا آلية عمل كل عملية، يبقى السؤال: أيهما نستخدم؟ كلاهما يُعطي النتيجة نفسها. تُعدّ المنشئات خيارًا رائعًا لإضافة أو إزالة خاصية من أي كائن يرث من المنشئ. مع ذلك، يُمكن فهم دوال المصنع بسهولة أكبر، لأنها في النهاية مجرد دالة. بالنسبة لدوال المصنع، لا نحتاج إلى استخدام الكلمة المفتاحية "new". بفضل قوة عمليات الإغلاق، يُمكن أن تكون أكثر مرونة. باستخدامها، يُمكننا تحقيق ما يُسمى "خصوصية البيانات". لنلقِ نظرة على مثال آخر يشرح آلية عمل ذلك.
function createCar(make, model, year) {
return {
getFullName() {
return `${year} ${make} ${model}`;
}
}
}
const car1 = createCar('Toyota', 'Tacoma', 2018);
console.log(car1.getFullName()); // => 2018 Toyota Tacoma
console.log(car1.make); // => undefined
console.log(car1); // => { getFullName: [Function: getFullName] }نتيجة
بشكل عام، أهم ما في كتابة الكود الخاص بك هو أنه لا يوجد أي خطأ فيه بالضرورة. هناك طريقة جيدة للحفاظ على كودك واضحًا ومختصرًا. استخدم دوال المصنع ودوال البناء حيثما تراه مناسبًا لحالتك.









