23 سؤالًا صعبًا لمقابلات JavaScript

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


صورة

1. شرح ميزات التحقق من المساواة في جافا سكريبت


الصعوبة: *


لدى JavaScript عاملين للتحقق من تكافؤ القيم. الأول هو ما يسمى عامل المساواة الصارم. والثاني هو عامل المساواة غير الصارم ، والذي يمكن استخدامه لتحويل أنواع الكميات المحددة.

  • ===يتحقق عامل المساواة الصارم ( ) من قيم المساواة دون إجراء تحويلات النوع.
  • ==يتحقق عامل المساواة غير الصارم ( ) من قيم المساواة ، ويحولها إلى نوع شائع.

var a = "42";
var b = 42;

a == b;         // true
a === b;        // false

فيما يلي بعض الإرشادات لاستخدام أدوات التحقق من المساواة المختلفة في 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!" );
})();
// "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); // [2, 4, 6]

المصدر

8. ما هو الفرق بين طريقة Object.freeze () والكلمة الأساسية const؟


الصعوبة: ***


الكلمة الرئيسية constوالطريقة Object.freeze()هي أشياء مختلفة تماما. تنطبق

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

const person = {
    name: "Leonardo"
};
let animal = {
    species: "snake"
};
person = animal; // Uncaught TypeError: Assignment to constant variable.

Object.freeze()تعمل الطريقة مع القيم. أو بالأحرى مع قيم الكائنات. يجعل الكائن غير قابل للتغيير ، والذي يحمي من التغييرات في قيمة خصائص هذا الكائن.

let person = {
    name: "Leonardo"
};
Object.freeze(person);
person.name = "Lima"; // Uncaught TypeError: Cannot assign to read only property 'name' of object
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')); // false

إذا كنت لا تزال بحاجة إلى إزالة هذه الخاصية ، يمكنك القيام بذلك إما عن طريق الاتصال بالكائن Employee( delete Employee.company) مباشرة ، أو عن طريق الاتصال بالنموذج الأولي للكائن emp1باستخدام خاصيته __proto__( delete emp1.__proto__.company).

المصدر

14. أخبرنا عن نمط تصميم النموذج الأولي.


الصعوبة: ****


النموذج الأولي هو نمط تصميم عام. يتم استخدامه لإنشاء كائنات. تحتوي الكائنات التي تم إنشاؤها باستخدامها على قيم منسوخة من نموذجها الأولي (من نموذج العينة). يسمى هذا القالب أيضًا بقالب الخصائص.

مثال على استخدام نمط "النموذج الأولي" هو تهيئة كائنات معينة بقيم قياسية مخزنة في قاعدة البيانات. يتم نسخ هذه القيم المسجلة في النموذج الأولي إلى كائنات جديدة دون الوصول إلى قاعدة البيانات.

وتجدر الإشارة إلى أن هذا النمط نادرًا ما يستخدم في اللغات الكلاسيكية. تستخدم جافا سكريبت نموذج وراثة نموذج أولي. يستخدم هذا النمط في تصميم الأشياء الجديدة ونماذجها الأولية.

المصدر

15. ما هي "المنطقة الميتة المؤقتة" في ES6؟


الصعوبة: ****


أجرى ES6 رفع المتغيرات والثوابت أعلنت باستخدام الكلمات الرئيسية letو const(يتم ذلك وصعود الكيان أعلن باستخدام الكلمات الأساسية var، classو function). ومع ذلك ، فإن الشفرة تحتوي على منطقة تمتد من دخول النطاق إلى الإعلان عن متغير أو ثابت. عند الوصول إلى متغير أو ثابت في هذه المنطقة ، سيتم إنشاء خطأ. هذه هي "المنطقة الميتة المؤقتة" (TDZ).

//console.log(aLet)  //  ReferenceError

let aLet;
console.log(aLet); // undefined
aLet = 10;
console.log(aLet); // 10

في هذا المثال ، ينتهي TDZ بعد الإعلان aLet، ولكن ليس بعد تعيين aLetالقيمة.

المصدر

16. هل يمكنك وصف الفرق الرئيسي بين forEach () وطرق صفيف map ()؟ في أي حالات تفضل إحدى هذه الطرق على أخرى؟


الصعوبة: ****


من أجل فهم الفرق بين هذه الأساليب ، دعونا نتحدث عن ميزات كل منها.

إليك كيفية العمل .forEach():

  • يتكرر فوق عناصر المصفوفة.
  • ينفذ وظيفة رد الاتصال التي تم تمريرها إليها لكل عنصر من عناصر الصفيف.
  • لا تعيد أي شيء.

const a = [1, 2, 3];
const doubled = a.forEach((num, index) => {
  //  -  num /  index.
});

// doubled = undefined

فيما يلي وصف موجز للطريقة .map():

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

const a = [1, 2, 3];
const doubled = a.map(num => {
  return num * 2;
});

// doubled = [2, 4, 6]

ونتيجة لذلك، اتضح أن الفرق الرئيسي بين .forEach()و .map()هو أنه .map()إرجاع مجموعة جديدة. إذا كنت بحاجة إلى الحصول على نتيجة تحويل عناصر الصفيف الأصلي دون تغيير هذا الصفيف ، فعليك الاختيار .map(). إذا كنت تحتاج فقط إلى التكرار على عناصر المصفوفة - فيمكنك استخدامها .forEach().

المصدر

17. ما هو الفرق بين متغير غير معلن ومتغير يحتوي على قيمة فارغة ومتغير غير محدد؟ كيف تتحقق من متغير لحقيقة أنه غير معلن ، وكذلك غير محدد وغير محدد؟


الصعوبة: ****


يتم إنشاء متغير غير معلن عند تعيين قيمة لمعرف لم يتم تعريفه مسبقًا باستخدام var، letأو const. يتم الإعلان عن المتغيرات غير المعلنة في النطاق العالمي ، خارج النطاق الحالي. في الوضع الصارم ، يتم طرح استثناء عند محاولة تعيين قيمة لمتغير غير معلن ReferenceError. لا يُنصح باستخدام المتغيرات غير المعلنة - تمامًا كما لا يُنصح باستخدام المتغيرات العامة. يجب تجنبها بكل الوسائل. من أجل حماية نفسك من عواقب استخدام المتغيرات غير المعلنة ، استخدم الكتلة try/catch.

function foo() {
  x = 1; //     ReferenceError
}

foo();
console.log(x); // 1

المتغير المحتوي undefinedهو متغير معلن ولم يتم تعيين قيمة له. undefinedتشكل القيمة نوع البيانات الخاص بها. إذا لم تُرجع الدالة أي شيء ، وكانت نتيجة استدعائها مكتوبة إلى متغير ، فستقع في هذا المتغير undefined. من أجل تنظيم فحص undefined، يمكنك استخدام عامل المساواة الصارم ( ===) أو عامل التشغيل typeofالذي يُرجع سلسلة undefined. يرجى ملاحظة أن عند التحقق من و، undefinedيجب عدم استخدام المشغل المساواة غير صارم ( ==)، لأنها تعتبر undefinedو القيم لتكون على قدم المساواة null.

var foo;
console.log(foo); // undefined
console.log(foo === undefined); // true
console.log(typeof foo === 'undefined'); // true

console.log(foo == null); // true.        undefined!

function bar() {}
var baz = bar();
console.log(baz); // undefined

nullيجب تعيين متغير يحتوي على قيمة بشكل صريح على هذه القيمة. إنه يرمز إلى عدم وجود معنى ويختلف عن - undefinedمتغير في أن القيمة الواردة فيه تم تعيينها صراحة له. من أجل التحقق من القيمة null، يكفي استخدام عامل المساواة الصارم. للتحقق null، كما هو الحال في التحقق من ذلك undefined، لا ينبغي للمرء استخدام عامل المساواة غير الصارم ، الذي يعتبر قيم nullو يساوي undefined.

var foo = null;
console.log(foo === null); // true
console.log(typeof foo === 'object'); // true

console.log(foo == undefined); // true        null!

أحاول ألا أترك المتغيرات أبدًا في حالة غير معلنة ، أو في حالة يتم فيها الإعلان عنها ، ولكن لم يتم تعيينها صراحةً لأي قيمة. إذا كنت لن أكتب قيمة إلى متغير بعد إعلانه مباشرة ، فأنا أكتب إليه 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();        // : This is a method I want to expose!
Exposer.second();       // : Inside a private method!
Exposer.methodToExpose; // undefined

العيب الواضح لهذا القالب هو أنه لا يمكنك استخدام الأساليب الخاصة عند استخدامه.

المصدر

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); // { name: 'Leonardo', profession: { name: 'doctor' } }

هنا هو "التجميد العميق":

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"; // TypeError: Cannot assign to read only property 'name' of object

يتم عرض رسالة الخطأ فقط في وضع صارم. في الوضع العادي ، لا تتغير القيمة بدون رسائل خطأ.

المصدر

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    
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;
});

المصدر

عزيزي القارئ! ما هي أسئلة جافا سكريبت التي توصلت إليها خلال مقابلاتك؟


All Articles