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

1. شرح ميزات التحقق من المساواة في جافا سكريبت
الصعوبة: *
لدى JavaScript عاملين للتحقق من تكافؤ القيم. الأول هو ما يسمى عامل المساواة الصارم. والثاني هو عامل المساواة غير الصارم ، والذي يمكن استخدامه لتحويل أنواع الكميات المحددة.===
يتحقق عامل المساواة الصارم ( ) من قيم المساواة دون إجراء تحويلات النوع.==
يتحقق عامل المساواة غير الصارم ( ) من قيم المساواة ، ويحولها إلى نوع شائع.
var a = "42";
var b = 42;
a == b;
a === b;
فيما يلي بعض الإرشادات لاستخدام أدوات التحقق من المساواة المختلفة في JavaScript:- إذا كان أي من القيم التي تمت مقارنتها يمكن أن تكون قيمة
true
أو false
- حاول تجنب عامل التشغيل ==
. استخدم عامل ===
. - استخدام المشغل
===
في حالة ما إذا كنت تعمل مع القيم التالية: 0
، «»
أو []
(مجموعة فارغة). - في جميع الحالات الأخرى ، يمكنك استخدام عامل التشغيل بأمان
==
. علاوة على ذلك ، هذا ليس آمنًا فحسب ، بل يساعد أيضًا في تبسيط التعليمات البرمجية وتحسين إمكانية قراءتها.
→ المصدر2. أعط أمثلة على الصب إلى نوع منطقي من القيم التي لا تتعلق بهذا النوع
الصعوبة: ***
جوهر هذا السؤال هو معرفة أي القيم ، في حالة تحويلها إلى نوع منطقي ، تتحول false
، وأي - في true
.فيما يلي قائمة بالقيم التي يمكن تسميتها "زائفة". عند التحويل إلى نوع منطقي ، يتحولون إلى قيمة false
:«»
(سطر فارغ).0
، -0
، NaN
(وليس رقم).null
، undefined
.
"خطأ" معنى منطقي false
.أي قيمة غير مدرجة في هذه القائمة ، عندما يتم تحويلها إلى نوع منطقي ، تتحول إلى true
(تسمى هذه القيم "صواب" - صدق). على سبيل المثال:«hello»
.42
.[ ]
، [ 1, «2», 3 ]
(المصفوفات).{ }
، { a: 42 }
(الكائنات).function foo() { .. }
(المهام).
"صحيح" هو أيضا معنى منطقي true
.→ المصدر3. ما هو معهد التمويل الدولي؟
الصعوبة: ***
IIFE (تعبير دالة تم استدعاؤه فورًا) هو تعبير وظيفي يتم استدعاؤه على الفور. يتم تنفيذ هذا التعبير مباشرة بعد الإنشاء.(function IIFE(){
console.log( "Hello!" );
})();
غالبًا ما يُستخدم هذا النمط لمنع تلوث مساحة الاسم العالمية. والحقيقة هي أن المتغيرات المعلنة في IIFE (كما هو الحال في أي وظيفة عادية أخرى) غير مرئية خارج هذه الوظيفة.→ المصدر4. متى يجب علي استخدام وظائف الأسهم التي ظهرت في ES6؟
الصعوبة: ***
فيما يلي قواعد بسيطة لاستخدام الطرق المختلفة لإعلان الوظائف التي أتبعها عند تطوير التعليمات البرمجية للبيئات التي تدعم ES6 والمعايير الأحدث:- استخدم الكلمة الأساسية
function
في النطاق العالمي ومن أجل الخصائص Object.prototype
. - استخدم الكلمة الأساسية لمنشئي
function
الكائن. - في حالات أخرى ، استخدم دالات الأسهم.
كما ترى ، يوصى باستخدام وظائف الأسهم في كل مكان تقريبًا. هناك عدة أسباب لهذا الوضع:- عمل ملائم مع السياق. تستخدم دالات السهم قيمة
this
السياق المحيط دون أن يكون لها الخاصة بها this
. إذا تم استخدام هذه الوظائف بالتتابع ، دون استخدام الوظائف العادية في الإنشاءات المعقدة ، فهذا يضمن العمل الآمن مع السياق. - الدمج. كود وظيفة السهم أسهل في الدخول وأسهل في القراءة. ربما تبدو لك هذه الميزة لوظائف الأسهم على الوظائف العادية مثيرة للجدل وتعتمد على وجهة نظر كل مطور معين.
- وضوح الكود. إذا تم تمثيل جميع التعليمات البرمجية تقريبًا بوظائف الأسهم ، يتم تمييز أي وظيفة عادية في هذه التعليمات البرمجية عن طريق إنشاء سياقها الخاص. باستخدام وظائف السهم ، يقوم المبرمج بإنشاء كود أكثر قابلية للفهم يسهل العمل به من التعليمات البرمجية بدون وظائف السهم
this
.
→ المصدر5. ما الفرق بين فئات ES6 ومنشئي الوظائف؟
الصعوبة: ***
أولاً ، ضع في اعتبارك الأمثلة.وظيفة المنشئ:function Person(name) {
this.name = name;
}
فئة ES6:class Person {
constructor(name) {
this.name = name;
}
}
عندما يتعلق الأمر بإنشاء كائنات بسيطة ، تبدو المنشئات والفئات المستخدمة لهذا الغرض متشابهة جدًا.يظهر الفرق الرئيسي بين المنشئين والفئات عند استخدام الميراث. إذا كنا بحاجة إلى إنشاء فئة Student
هي فئة فرعية من الفئة Person
وإضافة حقل إلى هذه الفئة الجديدة studentId
، فهذه هي الكيفية التي سيستخدم بها المُنشئون والشفرة التي يتم استخدام الفئات بها.وظيفة المنشئ:function Student(name, studentId) {
Person.call(this, name);
this.studentId = studentId;
}
Student.prototype = Object.create(Person.prototype);
Student.prototype.constructor = Student;
فئة ES6:class Student extends Person {
constructor(name, studentId) {
super(name);
this.studentId = studentId;
}
}
→ المصدر6. أخبرنا عن طريقة Function.prototype.bind ().
الصعوبة: ***
لاقتباس MDN: " bind()
تنشئ الطريقة وظيفة جديدة تقوم ، عند استدعائها ، بتعيين this
القيمة المقدمة كسياق التنفيذ . يتم تمرير مجموعة الوسائط أيضًا إلى الطريقة ، والتي سيتم تعيينها قبل تمرير الوسائط إلى الدالة المنضمة عندما يتم استدعاؤها. "أعتقد أن هذه الطريقة. bind()
مفيد بشكل خاص لقيم الربط this
في أساليب الفئة التي تحتاج إلى تمريرها إلى وظائف أخرى. غالبًا ما تستخدم هذه التقنية في مكونات التفاعل.→ المصدر 7. ما هي الوظائف المجهولة التي يشيع استخدامها؟
الصعوبة: ***
يتم استخدام الدوال المجهولة لإنشاء تركيبات IIFE ، وهي المتغيرات المعلنة التي لا تلوث النطاق العالمي.(function() {
})();
يتم استخدام الوظائف المجهولة كوظائف رد الاتصال ، والتي يتم استخدامها فقط في مكان واحد من البرنامج. سيبدو الرمز أكثر اكتفاء ذاتيًا وأكثر قابلية للقراءة إذا تم الإعلان عن رد الاتصال مباشرة في المكان الذي يتم استخدامه فيه. هذا يلغي الحاجة إلى إلقاء نظرة على الرمز بحثًا عن نص الوظيفة.setTimeout(function() {
console.log('Hello world!');
}, 1000);
يتم استخدام الوظائف المجهولة بشكل ملائم في الإنشاءات الخاصة بنمط البرمجة الوظيفية ، أو عند العمل مع مكتبات مثل Lodash (حالة الاستخدام هذه مشابهة لاستخدامها كرد اتصال).const arr = [1, 2, 3];
const double = arr.map(function(el) {
return el * 2;
});
console.log(double);
→ المصدر8. ما هو الفرق بين طريقة Object.freeze () والكلمة الأساسية const؟
الصعوبة: ***
الكلمة الرئيسية const
والطريقة Object.freeze()
هي أشياء مختلفة تماما. تنطبقالكلمة الرئيسية const
على الروابط ("المتغيرات"). يخلق ارتباطًا ثابتًا ، أي أنه من const
المستحيل ربط شيء جديد بمتغير (ثابت) معلن باستخدام كلمة رئيسية . لا يمكن تعيين قيمة ثابتة جديدة.const person = {
name: "Leonardo"
};
let animal = {
species: "snake"
};
person = animal;
Object.freeze()
تعمل الطريقة مع القيم. أو بالأحرى مع قيم الكائنات. يجعل الكائن غير قابل للتغيير ، والذي يحمي من التغييرات في قيمة خصائص هذا الكائن.let person = {
name: "Leonardo"
};
Object.freeze(person);
person.name = "Lima";
console.log(person);
يرجى ملاحظة أن رسالة الخطأ يتم عرضها في وضع صارم. في الوضع العادي ، لا تعمل عملية تغيير خاصية الكائن "المجمد" ببساطة.→ المصدر9. ما هو "المولد"؟
الصعوبة: ***
المولدات هي وظائف يمكنك من خلالها "الخروج" والتي يمكنك من خلالها "الدخول" حسب الضرورة. يتم الحفاظ على سياقها (الارتباطات المتغيرة) بين جلسات "الدخول" إليها. يتم الإعلان عن المولدات باستخدام كلمة أساسية function*
. مثل هذه الوظيفة ، عندما يتم استدعاؤها لأول مرة ، لا تنفذ التعليمات البرمجية ، وتعيد كائنًا خاصًا ، ومولدًا ، مما يسمح لك بالتحكم في تنفيذه. للحصول على القيمة التالية الصادرة عن المولد ، تحتاج إلى استدعاء طريقته next()
. ونتيجة لذلك ، يتم تنفيذ رمز الوظيفة حتى تصادف كلمة رئيسية yield
تُرجع قيمة.يمكن استدعاء وظيفة المولد عدة مرات كما تشاء. في كل مرة يعود مولد جديد. ولكن يمكن تجاوز كل مولد مرة واحدة فقط.function* makeRangeIterator(start = 0, end = Infinity, step = 1) {
let iterationCount = 0;
for (let i = start; i < end; i += step) {
iterationCount++;
yield i;
}
return iterationCount;
}
→ المصدر10. متى يجب استخدام المولدات؟
الصعوبة: ***
إذا كنت باختصار لوصف الميزات المفيدة الرئيسية للمولدات ، اتضح أنها كما يلي:- يحدد الرمز الذي يتم فيه استخدام المولد لحظة استلام القيمة التالية. المولد مسؤول فقط عن إرجاع القيم ، يتم التحكم فيه من الخارج.
- هناك مولدات غير متزامنة. تسمح لك بالعمل مع تدفقات البيانات غير المتزامنة.
الشيء الرئيسي في المولدات هو أنه يمكنك الحصول على القيمة التالية التي يتم إرجاعها بواسطة المولد فقط عند الحاجة إليها في التعليمات البرمجية التي تستخدم المولد. المولدات لا تعيد كل شيء دفعة واحدة. في بعض الحالات ، قد تكون هذه الميزة مريحة للغاية.→ المصدر11. ما هو "رفع المتغيرات"؟
الصعوبة: ****
إن جوهر مفهوم "رفع المتغيرات" هو أن الإعلانات "ترتفع" إلى أعلى النطاق الحالي. ونتيجة لذلك ، يمكن استخدام المتغير قبل إعلانه. يتم رفع التصريحات المتغيرة فقط ، ولكن ليس رمز التهيئة الخاص بهم. لاحظ أن سلوك المتغيرات المعلنة باستخدام الكلمة الأساسية var
يختلف عن سلوك المتغيرات والثوابت المعلنة باستخدام let
و const
.→ المصدر12. ماذا سيتم إخراج التعليمات البرمجية التالية؟
الصعوبة: ****
var output = (function(x) {
delete x;
return x;
})(0);
console.log(output);
سيتم إخراج هذا الرمز 0
. يتم delete
استخدام عامل التشغيل لحذف خصائص الكائنات. و x
- هذه ليست خاصية كائن - إنها متغير محلي. delete
لا يؤثر عامل التشغيل على المتغيرات المحلية.→ المصدر13. ماذا سيتم إخراج التعليمات البرمجية التالية؟
الصعوبة: ****
var Employee = {
company: 'xyz'
}
var emp1 = Object.create(Employee);
delete emp1.company
console.log(emp1.company);
سيتم إخراج هذا الرمز xyz
. الخاصية company
ليست خاصية كائن emp1
، ولكنها خاصية من نموذجها الأولي. المشغل delete
لا يحذف خصائص النموذج من الكائنات. الكائن emp1
ليس له ممتلكاته الخاصة company
. يمكنك التحقق من ذلك عن طريق:console.log(emp1.hasOwnProperty('company'));
إذا كنت لا تزال بحاجة إلى إزالة هذه الخاصية ، يمكنك القيام بذلك إما عن طريق الاتصال بالكائن Employee
( delete Employee.company
) مباشرة ، أو عن طريق الاتصال بالنموذج الأولي للكائن emp1
باستخدام خاصيته __proto__
( delete emp1.__proto__.company
).→ المصدر14. أخبرنا عن نمط تصميم النموذج الأولي.
الصعوبة: ****
النموذج الأولي هو نمط تصميم عام. يتم استخدامه لإنشاء كائنات. تحتوي الكائنات التي تم إنشاؤها باستخدامها على قيم منسوخة من نموذجها الأولي (من نموذج العينة). يسمى هذا القالب أيضًا بقالب الخصائص.مثال على استخدام نمط "النموذج الأولي" هو تهيئة كائنات معينة بقيم قياسية مخزنة في قاعدة البيانات. يتم نسخ هذه القيم المسجلة في النموذج الأولي إلى كائنات جديدة دون الوصول إلى قاعدة البيانات.وتجدر الإشارة إلى أن هذا النمط نادرًا ما يستخدم في اللغات الكلاسيكية. تستخدم جافا سكريبت نموذج وراثة نموذج أولي. يستخدم هذا النمط في تصميم الأشياء الجديدة ونماذجها الأولية.→ المصدر15. ما هي "المنطقة الميتة المؤقتة" في ES6؟
الصعوبة: ****
أجرى ES6 رفع المتغيرات والثوابت أعلنت باستخدام الكلمات الرئيسية let
و const
(يتم ذلك وصعود الكيان أعلن باستخدام الكلمات الأساسية var
، class
و function
). ومع ذلك ، فإن الشفرة تحتوي على منطقة تمتد من دخول النطاق إلى الإعلان عن متغير أو ثابت. عند الوصول إلى متغير أو ثابت في هذه المنطقة ، سيتم إنشاء خطأ. هذه هي "المنطقة الميتة المؤقتة" (TDZ).
let aLet;
console.log(aLet);
aLet = 10;
console.log(aLet);
في هذا المثال ، ينتهي TDZ بعد الإعلان aLet
، ولكن ليس بعد تعيين aLet
القيمة.→ المصدر16. هل يمكنك وصف الفرق الرئيسي بين forEach () وطرق صفيف map ()؟ في أي حالات تفضل إحدى هذه الطرق على أخرى؟
الصعوبة: ****
من أجل فهم الفرق بين هذه الأساليب ، دعونا نتحدث عن ميزات كل منها.إليك كيفية العمل .forEach()
:- يتكرر فوق عناصر المصفوفة.
- ينفذ وظيفة رد الاتصال التي تم تمريرها إليها لكل عنصر من عناصر الصفيف.
- لا تعيد أي شيء.
const a = [1, 2, 3];
const doubled = a.forEach((num, index) => {
});
فيما يلي وصف موجز للطريقة .map()
:- يتكرر فوق عناصر المصفوفة.
- يقوم بتحويل كل عنصر من عناصر المصفوفة الأصلية إلى عنصر من المصفوفة الجديدة ، واستدعاء الوظيفة التي تم تمريرها إليه لكل عنصر من المصفوفة الأصلية.
const a = [1, 2, 3];
const doubled = a.map(num => {
return num * 2;
});
ونتيجة لذلك، اتضح أن الفرق الرئيسي بين .forEach()
و .map()
هو أنه .map()
إرجاع مجموعة جديدة. إذا كنت بحاجة إلى الحصول على نتيجة تحويل عناصر الصفيف الأصلي دون تغيير هذا الصفيف ، فعليك الاختيار .map()
. إذا كنت تحتاج فقط إلى التكرار على عناصر المصفوفة - فيمكنك استخدامها .forEach()
.→ المصدر17. ما هو الفرق بين متغير غير معلن ومتغير يحتوي على قيمة فارغة ومتغير غير محدد؟ كيف تتحقق من متغير لحقيقة أنه غير معلن ، وكذلك غير محدد وغير محدد؟
الصعوبة: ****
يتم إنشاء متغير غير معلن عند تعيين قيمة لمعرف لم يتم تعريفه مسبقًا باستخدام var
، let
أو const
. يتم الإعلان عن المتغيرات غير المعلنة في النطاق العالمي ، خارج النطاق الحالي. في الوضع الصارم ، يتم طرح استثناء عند محاولة تعيين قيمة لمتغير غير معلن ReferenceError
. لا يُنصح باستخدام المتغيرات غير المعلنة - تمامًا كما لا يُنصح باستخدام المتغيرات العامة. يجب تجنبها بكل الوسائل. من أجل حماية نفسك من عواقب استخدام المتغيرات غير المعلنة ، استخدم الكتلة try/catch
.function foo() {
x = 1;
}
foo();
console.log(x);
المتغير المحتوي undefined
هو متغير معلن ولم يتم تعيين قيمة له. undefined
تشكل القيمة نوع البيانات الخاص بها. إذا لم تُرجع الدالة أي شيء ، وكانت نتيجة استدعائها مكتوبة إلى متغير ، فستقع في هذا المتغير undefined
. من أجل تنظيم فحص undefined
، يمكنك استخدام عامل المساواة الصارم ( ===
) أو عامل التشغيل typeof
الذي يُرجع سلسلة undefined
. يرجى ملاحظة أن عند التحقق من و، undefined
يجب عدم استخدام المشغل المساواة غير صارم ( ==
)، لأنها تعتبر undefined
و القيم لتكون على قدم المساواة null
.var foo;
console.log(foo);
console.log(foo === undefined);
console.log(typeof foo === 'undefined');
console.log(foo == null);
function bar() {}
var baz = bar();
console.log(baz);
null
يجب تعيين متغير يحتوي على قيمة بشكل صريح على هذه القيمة. إنه يرمز إلى عدم وجود معنى ويختلف عن - undefined
متغير في أن القيمة الواردة فيه تم تعيينها صراحة له. من أجل التحقق من القيمة null
، يكفي استخدام عامل المساواة الصارم. للتحقق null
، كما هو الحال في التحقق من ذلك undefined
، لا ينبغي للمرء استخدام عامل المساواة غير الصارم ، الذي يعتبر قيم null
و يساوي undefined
.var foo = null;
console.log(foo === null);
console.log(typeof foo === 'object');
console.log(foo == undefined);
أحاول ألا أترك المتغيرات أبدًا في حالة غير معلنة ، أو في حالة يتم فيها الإعلان عنها ، ولكن لم يتم تعيينها صراحةً لأي قيمة. إذا كنت لن أكتب قيمة إلى متغير بعد إعلانه مباشرة ، فأنا أكتب إليه null
. إذا كنت تستخدم اللتر ، فإنه عادة ما يبلغ عن حالات استخدام متغيرات غير معلنة.→ المصدر18. حدثنا عن وحدة التصميم "وحدة مفتوحة"
الصعوبة: *****
نموذج "الكشف عن الوحدة النمطية" هو شكل من أشكال نموذج "الوحدة النمطية". الغرض من استخدام هذا النمط هو دعم التغليف واكتشاف بعض الخصائص والأساليب التي يتم إرجاعها في الكائن الحرفي. في ما يلي الشكل الذي سيبدو عليه التنفيذ المباشر لهذا النموذج:var Exposer = (function() {
var privateVariable = 10;
var privateMethod = function() {
console.log('Inside a private method!');
privateVariable++;
}
var methodToExpose = function() {
console.log('This is a method I want to expose!');
}
var otherMethodIWantToExpose = function() {
privateMethod();
}
return {
first: methodToExpose,
second: otherMethodIWantToExpose
};
})();
Exposer.first();
Exposer.second();
Exposer.methodToExpose;
العيب الواضح لهذا القالب هو أنه لا يمكنك استخدام الأساليب الخاصة عند استخدامه.→ المصدر19. ما الفرق بين خريطة وكائنات WeakMap؟
الصعوبة: *****
تتصرف هذه الكائنات بشكل مختلف في حالة عدم توفر متغير يحتوي على مرجع إلى كائن يمثل مفتاح أحد أزواج المفتاح / القيمة. هنا مثال:var map = new Map();
var weakmap = new WeakMap();
(function() {
var a = {
x: 12
};
var b = {
y: 12
};
map.set(a, 1);
weakmap.set(b, 2);
})()
بعد اكتمال تنفيذ IIFE ، لن يكون بإمكاننا الوصول إلى الكائنات a
و b
. لذلك ، يقوم جامع القمامة بإزالة المفتاح b
من weakmap
الذاكرة ومسحها. لكن المحتوى map
يبقى على حاله.ونتيجة لذلك ، اتضح أن الكائنات WeakMap
تسمح لمجمع القمامة بالتخلص من تلك السجلات التي لم تتم الإشارة إليها في المتغيرات الخارجية. map
تخزن الكائنات أزواج المفتاح / القيمة بغض النظر عن وجود أو عدم وجود مراجع مفاتيح خارجية. ويمكن قول الشيء نفسه عن تنفيذ هيكل البيانات Map
باستخدام المصفوفات العادية. و WeakMap
تستخدم "ضعيفة" المراجع الرئيسية. لا تتداخل مع تشغيل جامع القمامة إذا لم تكن هناك إشارات أخرى إلى الكائن المستخدم كمفتاح.→ المصدر20. كيف يتم تمرير المعلمات إلى وظيفة JavaScript: حسب المرجع أو بالقيمة؟
الصعوبة: *****
يتم تمرير المعلمات دائمًا بالقيمة ، ولكن تتم كتابة مراجع للكائنات إلى متغيرات تمثل كائنات. لذلك ، عندما يتم نقل كائن إلى دالة وتغيير خاصية هذا الكائن ، يتم حفظ هذا التغيير في الكائن عند إنهاء الوظيفة. ونتيجة لذلك ، هناك شعور بأن المعلمات في الوظيفة يتم تمريرها عن طريق المرجع. ولكن إذا قمت بتغيير قيمة المتغير الذي يمثل الكائن ، فلن يؤثر هذا التغيير على الكائنات الموجودة خارج الوظيفة.هنا مثال:function changeStuff(a, b, c)
{
a = a * 10;
b.item = "changed";
c = {item: "changed"};
}
var num = 10;
var obj1 = {item: "unchanged"};
var obj2 = {item: "unchanged"};
changeStuff(num, obj1, obj2);
console.log(num);
console.log(obj1.item);
console.log(obj2.item);
إليك ما سيخرجه هذا الرمز:10
changed
unchanged
→ المصدر21. كيفية تنظيم "تجميد عميق" لجسم ما؟
الصعوبة: *****
من أجل توفير "التجميد العميق" للكائن الذي تستخدمه Object.freeze()
، تحتاج إلى إنشاء وظيفة تعاودية "تجمد" خصائص الكائن ، والتي هي أيضًا كائنات.فيما يلي مثال على "تجميد" كائن عادي:let person = {
name: "Leonardo",
profession: {
name: "developer"
}
};
Object.freeze(person);
person.profession.name = "doctor";
console.log(person);
هنا هو "التجميد العميق":function deepFreeze(object) {
let propNames = Object.getOwnPropertyNames(object);
for (let name of propNames) {
let value = object[name];
object[name] = value && typeof value === "object" ?
deepFreeze(value) : value;
}
return Object.freeze(object);
}
let person = {
name: "Leonardo",
profession: {
name: "developer"
}
};
deepFreeze(person);
person.profession.name = "doctor";
يتم عرض رسالة الخطأ فقط في وضع صارم. في الوضع العادي ، لا تتغير القيمة بدون رسائل خطأ.→ المصدر22. لماذا يواجه مبرمجو جافا سكريبت مشكلة في استخدام هذه الكلمة الرئيسية؟
الصعوبة: *****
أهم شيء يجب فهمه this
هو أن الدوال ليس لها قيمة ثابتة this
. تعتمد هذه القيمة على كيفية استدعاء الوظيفة. إذا قلنا أن دالة يتم استدعاؤها بقيمة معينة this
، فهذا يعني أن هذه القيمة لا يتم تحديدها أثناء تعريف الوظيفة ، ولكن أثناء استدعائها. فيما يلي بعض الميزات this
:- إذا تم استدعاء الوظيفة بالشكل المعتاد (أي باستخدام بنية العرض
someFunc()
) ، this
فستشير إلى الكائن العام (في المستعرض هذا window
). إذا تم تنفيذ الرمز في وضع صارم ، this
ستتم كتابة قيمة إليه undefined
. - إذا تم استدعاء الوظيفة كطريقة لكائن ما ،
this
فسيتم تمثيل الكلمة الأساسية بالكائن الذي تنتمي إليه الطريقة. - call apply,
this
, call
apply
. - ,
this
. - ,
new
, this
, prototype
-. - إذا تم إنشاء الوظيفة باستخدام طريقة الربط ، فسيتم ربط الكلمة الأساسية
this
للدالة بشكل صارم بالقيمة التي تم تمريرها bind
كوسيطة أولى. هذا هو الاستثناء الوحيد للقاعدة القائلة بأن الدوال ليس لها قيمة مشفرة this
. الوظائف التي تم إنشاؤها باستخدام bind
ثابتة this
.
→ المصدر23. قارن استخدام البناء المتزامن / المنتظر والمولدات لتنفيذ نفس الوظيفة
الصعوبة: *****
- عند تكرار مولد باستخدام طريقة ،
.next()
تُرجع كل استدعاء لهذه الطريقة قيمة واحدة باستخدام الكلمة الرئيسية yield
. عند استخدام البناء غير المتزامن / الانتظار ، يتم تنفيذ تعبيرات الانتظار بالتسلسل. - يبسط تصميم غير متزامن / انتظار تنفيذ حالة استخدام مولد معينة.
- دائمًا ما يكون للقيم التي أرجعها المولد الشكل
{value: X, done: Boolean}
، وتقوم الدالات غير المتزامنة بإرجاع الوعود التي تم حلها بالقيمة X
، أو تفشل. - يمكن تحويل وظيفة غير متزامنة إلى مولد باستخدام الوعود. فيما يلي مثال على مثل هذا التحويل.
هنا هي الوظيفة غير المتزامنة:
async function init() {
const res1 = await doTask1();
console.log(res1);
const res2 = await doTask2(res1);
console.log(res2);
const res3 = await doTask3(res2);
console.log(res3);
return res3;
}
init();
هنا مولد مماثل.
function runner(genFn) {
const itr = genFn();
function run(arg) {
let result = itr.next(arg);
if (result.done) {
return result.value;
} else {
return Promise.resolve(result.value).then(run);
}
}
return run;
}
runner(function* () {
const res1 = await doTask1();
console.log(res1);
const res2 = await doTask2(res1);
console.log(res2);
const res3 = await doTask3(res2);
console.log(res3);
return res3;
});
→ المصدرعزيزي القارئ! ما هي أسئلة جافا سكريبت التي توصلت إليها خلال مقابلاتك؟