الجوا ب هو الخيار الثاني: B
لدينا الدالة `setTimeout` والتي تم استدعائها أولا, و لكن تم الخروج منها آخراً.
هذا لأن في المتصفح, ليس لدينا محرَك من نوع runtime, أيضا لدينا مايعرف ب `WebAPI`. هذا ال`WebAPI` يقوم بإعطائنا الدالة `setTimeout` لكي نبدأ بها, على سبيل المثال: DOM.
بعد ان يتم ارسال و البدء بتنفيذ ال _callback_ الى الWebAPI, الدالة `setTimeout` نفسها (ليس ال callback!) يتم اخراجها من الstack.
الآن, `foo` يتم إدخالها و البدء بتنفيذها, بينما `"First"` يتم تسجيل دخولها.
`foo` يتم إخراجها من ال stack, بينما `baz` يتم إدخالها و البدأ بتنفيذها. `"Third"` يتم تسجيل دخولها.
ال WebAPI ليس بإمكانها إضافة أشياء الى ال stack عندما تكون جاهزة. في المقابل, هي تقوم بإدخال دالة الcallback الى شيء يسمى بال _queue_.
هنا تحديدا المكان الذي تبدأ فيه الloop بالعمل.
ال **event loop** تنظر الى الstack و ال task queue, إذا كانت الstack خاوية, فهي تقوم بأخذ أول شيء في الqueue. و تقوم بإدخاله الى stack.
`bar` يتم إدخالها و البدأ بتنفيذها, `"Second"` يتم تسجيل دخولها, و من ثم إخراجها من الstack.
---
31. ماهو ال event.target عندما نقوم بالضغط على الزر
```html
الإجابة
الجواب هو الخيار الثالث: C
العنصر المتداخل الأعمق الذي تسبب بتنفيذ الevent هو العنصر الذي يستهدفه هذا الevent, بإمكانك إيقاف ال bubbling عن طريق `event.stopPropagation`.
---
32. عندما تقوم بالضغط على الفقرة (P), ماهو الناتج الذي ستتحصل عليه؟
```html
```
- A: `p` `div`
- B: `div` `p`
- C: `p`
- D: `div`
الإجابة
الجواب هو الخيار الأول: A
إذا قمنا بالضغط على `p` سنرى إثنان من الlogs, ألا و هما `p` و `div`, أثناء عملية event propagation, هنالك ثلاث مراحل: الا وهي capturing, target و bubbling. بصورة افتراضية, الevent handlers يتم تنفيذهم في مرحلة الbubbling (إلا في حال أنك قمت بضبط قيمة `useCapture` ل `true` ). هي تتسلسل ابتداءا من أعمق عنصر متداخل تصاعدا الى الأقل عمقاً.
---
33. ماهو الناتج؟
```javascript
const person = { name: "Lydia" };
function sayHi(age) {
console.log(`${this.name} is ${age}`);
}
sayHi.call(person, 21);
sayHi.bind(person, 21);
```
- A: `undefined is 21` `Lydia is 21`
- B: `function` `function`
- C: `Lydia is 21` `Lydia is 21`
- D: `Lydia is 21` `function`
الإجابة
الجواب هو الخيار الرابع: D
في الحالتين, بإمكاننا تمرير ال object الذي نود أن تشير اليه الكلمة المفتاحية `this`, ولكن, `.call` هي أيضا تم تنفيذها حالا.
`.bind.` تقوم بإرجاع نسخة من الدالة, ولكن مع سياق محدد, لذا هي لا يتم تنفيذها حالاً.
---
34. ماهو الناتج؟
```javascript
function sayHi() {
return (() => 0)();
}
console.log(typeof sayHi());
```
- A: `"object"`
- B: `"number"`
- C: `"function"`
- D: `"undefined"`
الإجابة
الجواب هو الخيار الثاني: B
دالة `sayHi` تقوم بإرجاع القيمة المرجعة من الدالة المناداة في اللحظة (IIFE). هذه الدالة تقوم بإرجاع `0`, و الذي نوعه عبارة عن `"number"`.
لمعلوماتك: لدينا فقط سبعة أنواع من ال built-in و هي : `null`, `undefined`, `boolean`, `number`, `string`, `object`, و `symbol`, و `bigint`.`"function"` هي ليست نوع, وبما أن الدوال عبارة عن objects, ف هي ليست من النوع `"object"`.
---
35. أي هذه القيم هي قيم خطئية؟
```javascript
0;
new Number(0);
("");
(" ");
new Boolean(false);
undefined;
```
- A: `0`, `''`, `undefined`
- B: `0`, `new Number(0)`, `''`, `new Boolean(false)`, `undefined`
- C: `0`, `''`, `new Boolean(false)`, `undefined`
- D: جميعها
الإجابة
الجواب هو الخيار الأول : A
لدينا فقط ستة قيم خطئية:
- `undefined`
- `null`
- `NaN`
- `0`
- `''` (empty string)
- `false`
Function constructors, مثل `new Number` و `new Boolean` هي قيم صحيحية.
---
36. ماهو الناتج؟
```javascript
console.log(typeof typeof 1);
```
- A: `"number"`
- B: `"string"`
- C: `"object"`
- D: `"undefined"`
الإجابة
الجواب هو الخيار الثاني: B
`typeof 1` تقوم بإرجاع `"number"`.
`typeof "number"` تقوم بإرجاع `"string"`
---
37. ماهو الناتج؟
```javascript
const numbers = [1, 2, 3];
numbers[10] = 11;
console.log(numbers);
```
- A: `[1, 2, 3, 7 x null, 11]`
- B: `[1, 2, 3, 11]`
- C: `[1, 2, 3, 7 x empty, 11]`
- D: `SyntaxError`
الإجابة
الجواب هو الخيار الثالث: C
عندما تقوم بضبط قيمة ما لعنصر في الarray , و بعد إضافة هذا العنصر انت تكون قد تجاوزت طول الarray, لغة الجافاسكريبت تنشيء شيئا يسمى ب "empty slots", أي خانة فارغة, و هي في الحقيقة تحمل القيمة `undefined`, و لكنك سترى شيئا كالتالي:
`[1, 2, 3, 7 x empty, 11]`
وذلك يعتمد على المكان الذي قمت فيه بتشغيل البرنامج ( هو مختلف لكل متصفح, node, ...الخ)
---
38. ماهو الناتج؟
```javascript
(() => {
let x, y;
try {
throw new Error();
} catch (x) {
(x = 1), (y = 2);
console.log(x);
}
console.log(x);
console.log(y);
})();
```
- A: `1` `undefined` `2`
- B: `undefined` `undefined` `undefined`
- C: `1` `1` `2`
- D: `1` `undefined` `undefined`
الإجابة
الجواب هو الخيار الأول : A
النطاق أو الblock `catch`يستقبل ال arguemnt الذي يساوي `x`, هذا ليس نفس القيمة `x` عندما قمنا بتمرير الarguments, هذا المتغير `x` هو متغير block-scoped, أي يتم التعامل معه أو مناداته فقط بداخل الblock الذي تم تعريفه به.
لاحقا, قمنا بضبط القيمة `1` لهذا المتغير من نوع block-scoped, وقمنا أيضا بضبط قيمة للمتغير `y`. الآن نحن نقوم بطباعة قيمة المتغير الذي من نوع block-scoped و الذي هو `x` عن طريق الlog, و الذي هو يساوي `1`.
بخارج نطاق ال`catch` block, `x` هي لاتزال `undefined`, و قيمة ال `y` تساوي `2`. عندما نريد طباعة قيمة ال x عن طريق الlog خارج نطاق ال `catch` block, فهي تقوم بإرجاع `undefined`, و ال `y` تقوم بإرجاع `2`.
---
39. كل شيء في الجافاسكريبت هو عبارة عن ...
- A: primitive أو object
- B: function أو object
- C: فقط objects , سؤال مخادع
- D: number or object
الإجابة
الجواب هو الخيار الأول: A
لغة الجافاسكريبت لديها فقط primitive types و objects.
نقصد بال Primitive types: `boolean`, `null`, `undefined`, `bigint`, `number`, `string`, و `symbol`.
مايميز ال primitive من ال object هو أن ال primitives ليس لديها أي خصائص أو methods; ولكنك ستلاحظ أن `'foo'.toUpperCase()`يتم تقييمها ومعالجتها الى `'FOO'`و لا نتحصل على الخطأ `TypeError`. هذا لأنه عندما تحاول الوصول الى خاصية أو method لمتغير من من نوع primitive مثل ال string, فإن لغة الجافاسكريبت ستقوم بشكل ضمني بعمل wrap لل object بإستخدام واحدة من ال wrapper Classes, أي مانعنيه `String`, و لاحقا بصورة مباشرة يقوم بالتخلص من الwrapper, بعد أن يتم تقييم و تنفيذ الexpression. جميع الprimitives, ماعدا `null` و `undefined` تقوم بعمل هذه العملية.
---
40. ماهو الناتج؟
```javascript
[[0, 1], [2, 3]].reduce(
(acc, cur) => {
return acc.concat(cur);
},
[1, 2]
);
```
- A: `[0, 1, 2, 3, 1, 2]`
- B: `[6, 1, 2]`
- C: `[1, 2, 0, 1, 2, 3]`
- D: `[1, 2, 6]`
الإجابة
الجواب هو الخيارالثالث: C
`[1, 2]` هي القيمة المبدئية.هذه القيمة هي التي بدأنا بها, و هي القيمة الأولى ل `acc`. أثناء الدورة الأولى`acc` تساوي `[1,2]` و `cur` تساوي `[0, 1]`, عندما نقوم بدمجهما سويا عن طريق concat يصبح لدينا الناتج `[1, 2, 0, 1]`.
إذاً, `[1, 2, 0, 1]` هي `acc` و `[2, 3]` هي `cur`. نقوم بدمجهما سوية و نتحصل على `[1, 2, 0, 1, 2, 3]`.
---
41. ماهو الناتج؟
```javascript
!!null;
!!"";
!!1;
```
- A: `false` `true` `false`
- B: `false` `false` `true`
- C: `false` `true` `true`
- D: `true` `true` `false`
الإجابة
الجواب هو الخيارالثاني: B
`null` قيمة خطئية.
`!null` تقوم بإرجاع `true`.
`!true` تقوم بإرجاع `false`.
*********
`""` قيمة خطئية.
`!""`تقوم بإرجاع `true`.
`!true` تقوم بإرجاع `false`.
*********
`1` قيمة صحيحية.
`!1` تقوم بإرجاع `false`.
`!false` تقوم بإرجاع `true`.
---
42. ماهو الذي تقوم الدالة `setInterval` بإرجاعه في المتصفح؟
```javascript
setInterval(() => console.log("Hi"), 1000);
```
A - رقم فريد أو متفرد id
B - قيمة محددة لل milliseconds
C - الدالة التي تم تمريرها
`undefined` - D
الإجابة
الجواب هو الخيار الأول: A
تقوم بإرجاع ال id الفريد, هذا الid يمكن استخدامه لكي يقوم بتصفير عداد الفترات المفصلة أي الinterval عن طريق استخدام الدالة `clearInterval()`
---
43. مالذي يتم ارجاعه بعد تنفيذ الكود أدناه؟
```javascript
[..."Lydia"];
```
- A: `["L", "y", "d", "i", "a"]`
- B: `["Lydia"]`
- C: `[[], "Lydia"]`
- D: `[["L", "y", "d", "i", "a"]]`
الإجابة
الجواب هو الخيار الأول: A
الstring هي تكرارية, و عملية الspread (...) تقوم بتحويل اي حرف تم فيه تنفيذ فئة تكرارية الى عنصر منفرد واحد.
---
44. ماهو الناتج؟
```javascript
function* generator(i) {
yield i;
yield i * 2;
}
const gen = generator(10);
console.log(gen.next().value);
console.log(gen.next().value);
```
- A: `[0, 10], [10, 20]`
- B: `20, 20`
- C: `10, 20`
- D: `0, 10 and 10, 20`
الإجابة
الجواب هو الخيار الثالث: C
الدوال العادية ليس بإمكانها ان تتوقف في وسط التنفيذ بعد أن يتم مناداتها, و لكن الدوال من نوع generator من الممكن أن يتم ايقافها وسط التنفيذ, و لاحقا يتم مواصلة تنفيذها من حيث المكان الذي توقفت به. في كل مرة تواجه فيها الدالة من نوع generator الكلمة المفتاحية `yield`, فإن الدالة تخضع أو تستسلم للقيمة المحددة بعدها. مع ملاحظة أن الدالة من نوع generator في هذه الحالة, لاتقوم بإرجاع القيمة, بل تخضع لتلك القيمة.
أولا, نقوم بإنشاء الدالة من نوع generator مع وجود المتغير `i` مساوي ل `10`. نقوم بمناداة الدالةمن نوع generator باستخدام الدالة `next()`. في المرة الأولى التي ننادي فيها الدالة من نوع generator, فإن ال `i` تساوي `10`. هي تواجه الكلمة المفتاحية `yield`, فتخضع لقيمة ال `i`. الدالة generator في هذه اللحظة تم توقيفها مؤقتا, و القيمة `10` تم طباعتها عن طريق log.
اذاً, نقوم بمناداة الدالة مرة أخرى عن طريق الدالة `next()`, هي تبدأ لتواصل من المكان الذي تم توقفيها فيه مؤقتا سابقاً, و ماتزال قيمة `i` تساوي `10`. الآن هي تواجه الكلمة المفتاحية `yield` التالية, و تواجه `i * 2`. `i` تساوي `10`,لهذا تقوم بإرجاع `10 * 2` و التي هي تساوي `20`, و هذا سيوصلنا للنتيجة `10, 20`.
---
45. ما الذي يتم ارجاعه عند تنفيذ الكود؟
```javascript
const firstPromise = new Promise((res, rej) => {
setTimeout(res, 500, "one");
});
const secondPromise = new Promise((res, rej) => {
setTimeout(res, 100, "two");
});
Promise.race([firstPromise, secondPromise]).then(res => console.log(res));
```
- A: `"one"`
- B: `"two"`
- C: `"two" "one"`
- D: `"one" "two"`
الإجابة
الجواب هو الخيار الثاني: B
عندما نقوم بتمرير عدد من الpromises للدالة `Promise.race`. فهي تقوم برفض أو فصل الpromise الاولى. للدالة `setTimeout` نحن نقوم بتمرير timer: 500ms لل promise الأولى و التي هي (`firstPromise`), و 100ms اي 100ملي ثانية للpromise الثانية والتي هي (`secondPromise`) هذا يعني ان ال `secondPromise` يتم فصلها اولاً مع القيمة `'two'`. `res` الآن تحمل قيمة `'two'`, وهي التي تم طباعتها عن طريق الlog.
---
46. ماهو الناتج؟
```javascript
let person = { name: "Lydia" };
const members = [person];
person = null;
console.log(members);
```
- A: `null`
- B: `[null]`
- C: `[{}]`
- D: `[{ name: "Lydia" }]`
الإجابة
الجواب هو الخيار الرابع: D
أولا, نقوم بتعريف المتغير `person` مع قيمة عبارة عن object لديه الخاصية `name`.
ثم ,نقوم بتعريف المتغير الذي يسمى ب `members`. نقوم بضيط قيمة أول عنصر في ال array بالقيمة التي يحملها المتغير `person`.
الobjects تتفاعل عن طريق الrefrence عندما نقوم بضبطها مساويةً لبعضها البعض, عندما تقوم بتعريف أو إنشاء refrence معين من متغير الى متغير آخر, أنت فعليا تقوم بعمل نسخة من ذلك الrefrence. (مع ملاحظة أنهم ليس لديهم نفس الrefrence)
ثم , نقوم بضبط قمية المتغير `person` بقيمة تساوي `null`.
نحن فقط نقوم بتعديل قيمة المتغير `person`, وليس أول عنصر في ال array, بما أن ذلك العنصر لديه refrence منسوخ من ال object. أول عنصر في `members` لا يزال لديه refrence للobject الأصلي. و عندما نقوم بطباع الarray `members` عن طريق الlog, فإن العنصر الأول لايزال يحمل قيمة الobject, و التي سيتم طباعتها عن طريق log.
---
47. ماهو الناتج؟
```javascript
const person = {
name: "Lydia",
age: 21
};
for (const item in person) {
console.log(item);
}
```
- A: `{ name: "Lydia" }, { age: 21 }`
- B: `"name", "age"`
- C: `"Lydia", 21`
- D: `["name", "Lydia"], ["age", 21]`
الإجابة
الجواب هو الخيار الثاني: B
بإستخدام `for-in` التكرارية, بامكاننا أن نصل الى جميع المفاتيح التي تخص object معين. في هذه الحالة `name` و `age`. ماوراء الكواليس, مفاتيح ال objects هي عبارة عن strings (إذا لم تكن هذه المفاتيح عبارة عن symbol), في أي حلقة من الحلقات التكرارية, نقوم بضبط القيمة `item`مساوية للمفتاح الحالي الذي هي تتكرر فيه اوعنده. أولا `item` تساوي `name`, و يتم طباعتها عن طريق الlog, ثم `item` تساوي `age` و التي ايضا تم طباعتها عن طريق الlog.
---
48. ماهو الناتج؟
```javascript
console.log(3 + 4 + "5");
```
- A: `"345"`
- B: `"75"`
- C: `12`
- D: `"12"`
الإجابة
الجواب هو الخيار الثاني: B
Operator associativity او ترابطية العامل هي الترتيب أو التسلسل الذي يقيم به الcompiler ال expressions, ف هو إما أن يكون من اليسار الى اليمين أو من اليمين الى اليسار. هذا يحدث فقط إذا كان جميع الoperators لديها نفس الأسبقية. لدينا فقط نوع واحد من الoperator ألا و هو `+`. بالإضافة الى التالي, الترابطية هي من اليسار الى اليمين.
`3 + 4` يتم تقييمها أولا. هذا مايعطينا الناتج الذي هو عبارة عن الرقم `7`.
`7 + '5'` تقوم بإرجاع الناتج `"75"` بسبب عملية ال coercion وهي العمليةالتي تقوم بالتحويل من نوع الى آخر, لغة الجافاسكريبت تقوم بتحويل الرقم `7` الى النوع string, أنظرالى السؤال رقم 15 في الأعلى. بإمكاننا عمل concatenate لمتغيرين من النوع string بإستخدام العملية `+`. `"7" + "5"` سترجع الناتج `"75"`.
---
49. ماهي قيمة `num`؟
```javascript
const num = parseInt("7*6", 10);
```
- A: `42`
- B: `"42"`
- C: `7`
- D: `NaN`
الإجابة
الجواب هو الخيار الثالث: C
فقط الأرقام الأولى في الstring يتم إرجاعها. بناءاً على _radix_ (الargument الثاني لكي يتم تحديدنوعية الرقم الذي نود أن نقوم بعمل parse له الى: base 10, hexadecimal, octal, binary, الخ. ). تقوم `parseInt` بالتحقق عن إذا ماكانت الحروف في الstring صالحة. و بمجرد أن تجد حرف غير صالح في ال radix, ف هي تقوم بإيقاف عملية الparsing مباشرة و تتجاهل الحروف التي تليه.
`*` ليست رقم صالح. هي فقط تقوم بعمل parse ل `"7"` الى عدد عشري `7`. `num` الآن تحمل القيمة `7`.
---
50. ماهو الناتج؟
```javascript
[1, 2, 3].map(num => {
if (typeof num === "number") return;
return num * 2;
});
```
- A: `[]`
- B: `[null, null, null]`
- C: `[undefined, undefined, undefined]`
- D: `[ 3 x empty ]`
الإجابة
الجواب هو الخيار الثالث: C
عندما يتم عمل mapping لل array, فإن قيمة `num` ستساوي قيمة العنصر الذي يتم حاليا المرور به, فكما نعرف أن الmapping يدور على جميع عناصر الarray. في هذه الحالة, العناصر عبارة عن أرقام, لهذا فإن شرط ال if statement `typeof num === "number"` يقوم بإرجاع `true`. دالة map تقوم بإنشاء array جديدة, و إدخال القيم المرجعة من الدالة في هذه الarray.
ولكن, لا نقوم بإرجاع قيمة. عندما لا نقوم بإرجاع قيمة من الدالة, فإن الدالة تقوم بإرجاع `undefined`. لكل عنصرٍ في الarray, فإن نطاق الدالة او نعني الfunction block يتم مناداته, لهذا لأي عنصر نقوم بإرجاع `undefined`.
---
51. ماهو الناتج؟
```javascript
function getInfo(member, year) {
member.name = "Lydia";
year = 1998;
}
const person = { name: "Sarah" };
const birthYear = "1997";
getInfo(person, birthYear);
console.log(person, birthYear);
```
- A: `{ name: "Lydia" }, "1997"`
- B: `{ name: "Sarah" }, "1998"`
- C: `{ name: "Lydia" }, "1998"`
- D: `{ name: "Sarah" }, "1997"`
الإجابة
الجواب هو الخيار الأول: A
الArguments يتم تمريرها عن طريق قيمها, إلا في حالة كان قيمتها عبارة عن object, ففي هذه الحالة يتم تمريرها عن طريق الrefrence. `birthYear` تم تمريرها عن طريق القيمة, و بما أنها من النوع string وليس object. عندما نقوم بتمرير الarguments عن طريق القيمة, فإن نسخة من هذه القيمة يتم إنشاءها (أنظر للسؤال رقم 46 في الاعلى).
المتغير `birthYear` لديه refrence للقيمة `"1997"`. الargument `year` أيضا لديه refrence للقيمة `"1997"`, لكنها ليست نفس القيمة التي `birthYear` لديها refrence لها. عندما نقوم بتحديث قيمة `year` عن طريق ضبط `year` تساوي ل `"1998"`, نحن فقط نقوم بتحديث قيمة `year`. `birthYear` لا تزال تساوي `"1997"`.
قيمة `person` هي object. الargument `member` لديه نسخة refrence لنفس الobject. عندما نقوم بتعديل او تحديث خاصية للobject `member`و الذي لديه refrence لها, فإن قيمة `person` ستتعدل و تتغير أيضا,بما أن كلاهما لديهما refrence لنفس الobject. الخصائص `person` و `name` هما الأىن مساويان للقيمة `"Lydia"`.
---
52. ماهو الناتج؟
```javascript
function greeting() {
throw "Hello world!";
}
function sayHi() {
try {
const data = greeting();
console.log("It worked!", data);
} catch (e) {
console.log("Oh no an error!", e);
}
}
sayHi();
```
- A: `"It worked! Hello world!"`
- B: `"Oh no an error: undefined`
- C: `SyntaxError: can only throw Error objects`
- D: `"Oh no an error: Hello world!`
الإجابة
الجواب هو الخيار الرابع: D
مع عبارة `throw` , بإمكاننا إنشاء errors حسب الطلب, أي ليست كا الإخطاء العامة في اللغة, بإستخدام هذه العبارة بإمكانك أن تضع exception, الexception يمكن أن يكون : string, number, boolean أو object. في هذه الحالة, الexcption لدينا هو ال string `'Hello world'`.
مع عبارة `catch`, بإمكاننا ان نحدد ما الذي يتوجب فعله عندما يتم وضع أو إلقاء الexception في نطاق ال `try`. تم إلقاء أو وضع exception: الstring `'Hello world'`. `e` الآن تساوي تلك الstring,log. هذا سيعطينا النتيجة `'Oh an error: Hello world'`.
---
53. ماهو الناتج؟
```javascript
function Car() {
this.make = "Lamborghini";
return { make: "Maserati" };
}
const myCar = new Car();
console.log(myCar.make);
```
- A: `"Lamborghini"`
- B: `"Maserati"`
- C: `ReferenceError`
- D: `TypeError`
الإجابة
الجواب هو الخيار الثاني: B
عندما تقوم بإرجاع خاصية, فإن قيمة هذه الخاصية هي تساوي القيمة المرجعة, ليس القيمة التي تم ضبطها في دالة الconstructor. نقوم بإرجاع ال string `"Maserati"`, لذا فإن `myCar.make` تساوي `"Maserati"`.
---
54. ماهو الناتج؟
```javascript
(() => {
let x = (y = 10);
})();
console.log(typeof x);
console.log(typeof y);
```
- A: `"undefined", "number"`
- B: `"number", "number"`
- C: `"object", "number"`
- D: `"number", "undefined"`
الإجابة
الجواب هو الخيار الأول : A
`let x = y = 10;` هي في الحقيقة إختصار ل:
```javascript
y = 10;
let x = y;
```
عندما نقوم بضبط قيمة`y` لكي تساوي `10`, فنحن فعليا نقوم بإضافة الخاصية `y` للglobal object. (`window` في المتصفح, `global` في Node). في المتصفح, `window.y` الآن تساوي `10`.
ثم, عندما نقوم بتعريف المتغير `x` بالقيمة `y` و التي هي في الحقيقة تساوي `10`. المتغيرات التي يتم تعريفها بالكلمة المفتاحية `let`هي متغيرات block scoped, أي يتم التعامل معها في النطاق الذي تم تعريفها فيه فقط, الدالة المناداة حاليا في هذه الحالة أي immediately-invoked function (IIFE). عندما نقوم بإستخدام العملية `typeof`, فإن المعامل `x` ليس معرف, نحن نحاول الوصول الى `x` خارج النطاق الذي تم تعريفه بها. هذا يعني أن `x` ليست معرفة. المتغيرات التي لم يتم وضع قيمة لها أو لم يتم تعريفها هي من النوع `"undefined"`. `console.log(typeof x)` تقوم بإرجاع `"undefined"`.
ولكن, نحن قمنا بإنشاء و تعريف global variable `y` عندما قمنا بضبط قيمة `y` لتساوي `10`. هذه القيمة يمكن الوصول إليها من أي مكان في البرنامج. `y` هي معرفة, و لديها قيمة من النوع `"number"`. `console.log(typeof y)` تقوم بإرجاع `"number"`.
---
55. ماهو الناتج؟
```javascript
class Dog {
constructor(name) {
this.name = name;
}
}
Dog.prototype.bark = function() {
console.log(`Woof I am ${this.name}`);
};
const pet = new Dog("Mara");
pet.bark();
delete Dog.prototype.bark;
pet.bark();
```
- A: `"Woof I am Mara"`, `TypeError`
- B: `"Woof I am Mara"`,`"Woof I am Mara"`
- C: `"Woof I am Mara"`, `undefined`
- D: `TypeError`, `TypeError`
الإجابة
الجواب هو الخيار الأول: A
بإمكاننا مسح خصائص object معين عن طريق استخدام الكلمة المفتاحية `delete`, أيضا يمكن فعل هذا في ال prototype. بمسح خاصية معينة من الprototype, فهي سيتم مسحها وبالتالي لن تكون موجودة في سلسلة الprototype. في هذه الحالة فإن الدالة `bark` لن تكون موجودة بعد الآن في الprototype بعد `delete Dog.prototype.bark`, ولكن بالرغم من هذا فنحن نحاول الوصول إليها.
عندما نحاول أن ننادي شيئا ما في دالة و هو ليس موجود في هذه الدالة, فإننا سنتحصل على الخطأ `TypeError`, و في هذه الحالة `TypeError: pet.bark is not a function` بما أن `pet.bark` هي `undefined`.
---
56. ماهو الناتج؟
```javascript
const set = new Set([1, 1, 2, 3, 4]);
console.log(set);
```
- A: `[1, 1, 2, 3, 4]`
- B: `[1, 2, 3, 4]`
- C: `{1, 1, 2, 3, 4}`
- D: `{1, 2, 3, 4}`
الإجابة
الجواب هو الخيار الرابع: D
ال object `Set` هو مجموعة من القيم الفريدة, أي القيمة بإمكانها أن تتواجد مرة واحدة فقط في المجموعة.
نقوم بتمرير التكراري أي نعني الiterable `[1, 1, 2, 3, 4]` بوجود قيمة مكررة ألا وهي `1` . بما أننا لا يمكن أن نضع قيمة واحدة مرتين في مجموعة, فإن واحدة من القيم المكررة سيتم إزالتها, و سيكون الناتج: `{1, 2, 3, 4}`.
---
57. ماهو الناتج؟
```javascript
// counter.js
let counter = 10;
export default counter;
```
```javascript
// index.js
import myCounter from "./counter";
myCounter += 1;
console.log(myCounter);
```
- A: `10`
- B: `11`
- C: `Error`
- D: `NaN`
الإجابة
الجواب هو الخيار الثالث: C
هنا يوجد لدينا module مستورد وهو قابل للقراءة فقط, ليس بإمكانك تعديل او تحديث الmodule المستورد, أي imported module. فقط الmodule الذي قام بتصديره هو القادر على تغيير قيمته.
عندما نحاول أن نزيد قيمة المتغير `myCounter`, سنتحصل على الخطأ `myCounter` هو قابل للقراءة فقط و ليس من الممكن تعديله.
---
58. ماهو الناتج؟
```javascript
const name = "Lydia";
age = 21;
console.log(delete name);
console.log(delete age);
```
- A: `false`, `true`
- B: `"Lydia"`, `21`
- C: `true`, `true`
- D: `undefined`, `undefined`
الإجابة
الجواب هو الخيار الأول: A
العامل `delete` تقوم بإرجاع قيمة boolen و هي `true` عندما تتم عملية المسح بنجاح, خلاف ذلك ستقوم بإرجاع `false`, ولكن المتغيرات المعرفة بالكلمات المفتاحية `var`, `const` أو `let` ليس بالإمكان مسحها بإستخدام العامل `delete`.
المتغير `name` تم تعريفه باستخدام الكلمة المفتاحية `const`, لهذا فإن عملية مسحه لم تتم بنجاح, وتم إرجاع القيمة `false`, عندما نقوم بضبط المتغير `age` ليساوي القيمة `21` فإننا فعليا نقوم بإضافة خاصية تسمى `age` للglobal object. بإمكانك أن تمسح خصائص من الobjects بنجاح بإستخدام هذه الطريقة , أيضا الglobal objects, لذا فإن `delete age` تقوم بإرجاع `true`.
---
59. ماهو الناتج؟
```javascript
const numbers = [1, 2, 3, 4, 5];
const [y] = numbers;
console.log(y);
```
- A: `[[1, 2, 3, 4, 5]]`
- B: `[1, 2, 3, 4, 5]`
- C: `1`
- D: `[1]`
الإجابة
الجواب هو الخيار الثالث: C
بإمكاننا إستخراج أو استخلاص القيم من arrays أو من objects عن طريق إستخدام الdestructing, على سبيل المثال:
```javascript
[a, b] = [1, 2];
```
قيمة `a` الآن تساوي `1`, و قيمة `b` الآن تساوي `2`. ماقمنا بفعله حقاً في هذا السؤال هو:
```javascript
[y] = [1, 2, 3, 4, 5];
```
هذا يعني أن قيمة `y` هي مساوية للقيمة الأولى في الarray, والتي هي عبارة عن نوع رقم يساوي `1`, عندما نقوم بطباعة `y` عن طريق الlog, فإن القيمة `1` هي التي يتم إرجاعها.
---
60. ماهو الناتج؟
```javascript
const user = { name: "Lydia", age: 21 };
const admin = { admin: true, ...user };
console.log(admin);
```
- A: `{ admin: true, user: { name: "Lydia", age: 21 } }`
- B: `{ admin: true, name: "Lydia", age: 21 }`
- C: `{ admin: true, user: ["Lydia", 21] }`
- D: `{ admin: true }`
الإجابة
الجواب هو الخيار الثاني: B
من الممكن دمج الobjects بإستخدام العامل spread `...`. هي تمكنك من إنشاء نسخ من أزواج ال key/value أي أزواج المفاتيح و القيم التي تنتمي الى object معين, و إضافتهم الى object آخر. في هذه الحالة, نحن نقوم بعمل نسخ من الobject `user`, و من ثم إضافتهم الى ال obejct `admin`. ال object `admin` الآن يتضمن نسخ عبارة عن أزواج مفاتيح و قيم, و هذا ما سبب في إعطاء النتيجة `{ admin: true, name: "Lydia", age: 21 }`.
---
61. ماهو الناتج؟
```javascript
const person = { name: "Lydia" };
Object.defineProperty(person, "age", { value: 21 });
console.log(person);
console.log(Object.keys(person));
```
- A: `{ name: "Lydia", age: 21 }`, `["name", "age"]`
- B: `{ name: "Lydia", age: 21 }`, `["name"]`
- C: `{ name: "Lydia"}`, `["name", "age"]`
- D: `{ name: "Lydia"}`, `["age"]`
الإجابة
الجواب هو الخيار الثاني: B
مع إستخدام `defineProperty` method, بإمكاننا إضافة خصائص جديدة لobject معين,أو تعديل خصائصه الحالية,. عندما نقوم بإضافة خاصية لobject بإستخدام `defineProperty` method, ف هي بطبيعة الحال ليست enumerable. ال `Object.keys` method تقوم بإرجاع جميع أسامي الخصائص من object معين و التي هي جميعها enumerable, في هذه الحالة `"name"` فقط.
الخصائص التي تم إضافتها بإستخدام `defineProperty` method هي بطبيعة الحال غير قابلة للتغيير أو التعديل. بإمكانك عمل override بإستخدام الخصائص `writable`, `configurable` و `enumerable`. بهذه الطريقة, ال `defineProperty` method ستعطيك تحكم أكثر بكثير على الخصائص التي قمت بإضافتها الى object معين.
---
62. ماهو الناتج؟
```javascript
const settings = {
username: "lydiahallie",
level: 19,
health: 90
};
const data = JSON.stringify(settings, ["level", "health"]);
console.log(data);
```
- A: `"{"level":19, "health":90}"`
- B: `"{"username": "lydiahallie"}"`
- C: `"["level", "health"]"`
- D: `"{"username": "lydiahallie", "level":19, "health":90}"`
الإجابة
الجواب هو الخيار الأول : A
ال argument الثاني من `JSON.stringify` هو replacer أي حالٍ محل شيء آخر, الreplacer إما أن يكون دالة أو يكون array, و سيمكنك من التحكم في كيفية و ماهية امكانية عمل stringified للقيم, أي تحويلها الى string.
إذا كان الreplacer هو عبارة عن array, فإن الخصائص التي أساميها مضمنة في الarray هي فقط التي يمكن إضافتها الى ال JSON string. في هذه الحالة, الخصائص التي تحمل الأسامي `"level"` و `"health"` فقط هي المضمنة, `"username"` غير مضمنة. `data` الآن تساوي `"{"level":19, "health":90}"`.
إذا كان الreplacer عبارة عن دالة, فإن هذه الدالة يتم مناداتها عند أي خاصية في الobject أنت تقوم بعمل stringifying لها.القيمة المرجعة من هذه الدالة ستكون قيمة الخاصية عندما تم إضافتها ل JSON string. إذا كانت القيمة `undefined`, فإن هذه الخاصية سيتم إستبعادها من الJSON string.
---
63. ماهو الناتج؟
```javascript
let num = 10;
const increaseNumber = () => num++;
const increasePassedNumber = number => number++;
const num1 = increaseNumber();
const num2 = increasePassedNumber(num1);
console.log(num1);
console.log(num2);
```
- A: `10`, `10`
- B: `10`, `11`
- C: `11`, `11`
- D: `11`, `12`
الإجابة
الجواب هو الخيار الأول : A
العامل الأحادي `++` يقوم أولا بإرجاع قيمة المعامل, ثم يقوم بزيادة قيمة هذا المعامل. قيمة `num1` تساوي `10`, و بما أن دالة `increaseNumber` أولا تقوم بإرجاع قيمة `num` و التي هي تساوي `10`, و تقوم بزيادة قيمة `num` لاحقاً فقط.
`num2` تساوي`10`, وبما أننا نقوم بتمرير `num1` ل `increasePassedNumber`. فإن `number` تساوي `10` والتي هي قيمة`num1`. مجدداً, العامل الأحادي `++`, أولاً يقوم بإرجاع قيمة المعامل, و من ثم زيادة قيمة المعامل. قيمة `number` تساوي`10`, إذاً `num2` تساوي `10`.