أقوم بنشر عدة أسئلة جافاسكريبت بصورة يومية على حسابي في انستغرام.
تتدرج الأسئلة إبتداءا من المستوى الأساسي أو البسيط الى المستوى المتقدم لإختبار مدى معرفتك بلغة الجافا سكريبت, قم بمراجعة و إنعاش معرفتك باللغة قليلا, أو قم بالتجهيز لمقابلة عمل لوظيفة مبرمج عن طريق هذه الأسئلة!
أقوم بتحديث هذا المستودع أسبوعيا بإضافة المزيد من الأسئلة. 💪 🚀
الأجوبة توجد في الجزء المطوي بالأسفل أدناه تحت كل سؤال على حدة, فقط قم بالضغط على كلمة الإجابة لكي تحصل على الإجابة, حظا موفقا ❤️
اللغات المتوفرة:
- ماهو الناتج ؟
function sayHi() {
console.log(name);
console.log(age);
var name = "Lydia";
let age = 21;
}
sayHi();
- A:
Lydia
andundefined
- B:
Lydia
andReferenceError
- C:
ReferenceError
and21
- D:
undefined
andReferenceError
الإجابة
في داخل الدالة, قمنا أولا بتعريف المتغير name
مع الكلمة المفتاحية var
. و هذا يعني ان المتغير قد حصلت له عملية hoisting والتي تعني انه قد تم حجز مساحة لهذا المتغير في هذه اللحظة مع قيمة مبدئية و التي هي undefined
إلى ان نقوم فعليا بتعريف قيمة له لاحقا.
لم نقم بتعريف المتغير name
بعد عندما قمنا بطباعته في السطر الاول من الدالة, لهذا لايزال يحمل القيمة undefined
.
المتغيرات التي تم تعريفها بجانب الكلمات المفتاحية let
و const
يتم عمل عملية hoisting لها أيضا, ولكن على عكس المتغيرات التي يتم تعريفها بجانب الكلمة المفتاحية var
, لا يتم تعريفها او الوصول اليها مالم نقم بإضافة قيمة لها فعليا. و يسمى هذا بال"temporal dead zone".عندما نحاول الوصول الى المتغيرات من النوع var
قبل ان يتم تعريفها, نتحصل على الخطأ التالي ReferenceError
.
- ماهو الناتج?
for (var i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 1);
}
for (let i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 1);
}
- A:
0 1 2
and0 1 2
- B:
0 1 2
and3 3 3
- C:
3 3 3
and0 1 2
الإجابة
بسبب ترتيب تسلسل الأحداث في الجافا سكريبت, دالة setTimeout
والتي هي دالة من نوع callbackقد تم استدعائها بعد ان تم تنفيذ ال loop. بماأن المتغير i
في الloop الاولى قد تم تعريفه عن طريق الكلمة المفتاحية var
فإن هذه القيمة هي global. أثناء تنفيذ هذه ال loop قد تم إضافة 1 الى المتغير var
في كل دورة باستخدام العملية ++
. بنهاية الدورة و عندما تم استدعاء الدالة setTimeout
كانت قيمة المتغير i
قد أصبحت تساوي 3
في المثال الأول.
في الloop الثانية ,تم تعريف المتغير i
باستخدام الكلمة المفتاحية let
المتغيرات التي يتم تعريفها باستخدام الكلمات المفتاحية let
و const
هي متغيرات تنتمي فقط للBlock الذي تم تعريفها بداخله, والذي هو بين القوسين, أثناءتنفيذ الloop, سنقوم بالتحصل على قيمة جديدة للمتغير i
في نهاية كل دورة , وأي قيمة تكون منتمية للScope بداخل الloop.
- ماهو الناتج?
const shape = {
radius: 10,
diameter() {
return this.radius * 2;
},
perimeter: () => 2 * Math.PI * this.radius
};
shape.diameter();
shape.perimeter();
- A:
20
and62.83185307179586
- B:
20
andNaN
- C:
20
and63
- D:
NaN
and63
الإجابة
يرجى ملاحظة أن قيمةdiameter
هي دالة Regular و في المقابل قيمة perimeter
هي دالة من النوع arrow.
في حال استخدام دوال ال arrow, الكلمة المفتاحية this
ترجع و تدل على المحيط الحالي الذي توجد به الكلمة المفتاحية, على عكس وجود الكلمة المفتاحية this
في الدالة العادية حيث أنها تعني اننا نقوم بمناداة perimeter
و هي لا تعني اننا نقصد الshape object بل نقصد الscope الذي يحاوطه, على سبيل المثال : Window.
لا توجد قيمة radius
في ذلك ال object لهذا يقوم بإرجاع القيمة undefined
.
- ماهو الناتج؟
+true;
!"Lydia";
- A:
1
andfalse
- B:
false
andNaN
- C:
false
andfalse
الإجابة
عملية الزيادة الأحادية هنا وجدت لكي تقوم بتحويل المعامل الى رقم, true
هي 1
, و false
هي 0
.
المتغير من نوع string 'Lydia'
هو قيمة صدقية أو حقيقية, بمعنى أنها تساوي true
. السؤال الذي نقوم بطرحه هنا, هو هل هذه القيمة الصدقية هي قيمة غير صدقية؟ اي تساوي false
؟ لهذا نتحصل على الجواب false
.
- أي الإجابات هو إجابة صحيحة؟
const bird = {
size: "small"
};
const mouse = {
name: "Mickey",
small: true
};
- A:
mouse.bird.size
غير صحيحة - B:
mouse[bird.size]
غير صحيحة - C:
mouse[bird["size"]]
غير صحيحة - D: كل الإجابات صحيحة
الإجابة
في لغة الجافا سكريبت, جميع مفاتيح الobjects هي من النوع string. الا اذا كانت عبارة عن symbol. حتى ولو أننا في بعض المرات لانقوم بوضع نوعها على انها string بصورة صريحة, ولكنها دائما يتم تحويلها الى نوع string وراء الكواليس.
لغة الجافاسكريبت تقوم بترجمةال statements.عندما نقوم باستعمال ال bracket notation, تقوم الجافا سكريبت اولا برؤية أول فتحة للقوس [
و تقوم بالمتابعة الى ان تجد قفلة هذا القوس ]
.فقط عندما تصل الى قفلة القوس حتى تقوم بتقييم ال statement و من ثم معالجتها.
mouse[bird.size]
: اولا تقوم بتقييمbird.size
, والتي هي تساوي "small"
. mouse["small"]
تقوم بإرجاعtrue
ولكن في المقابل, عندما نقوم بإستخدام ال dot notation,لا يتم معالجة الأمر هكذا. mouse
ليس لديها مفتاح يسمى bird
, و هذا يعني أن mouse.bird
هي قيمة undefined
. بالتالي نقوم بالسؤال عن الsize
بإستخدام ال dot notation: للسؤال عن قيمة mouse.bird.size
.
وبما أن mouse.bird
قيمتها undefined
ف نحن فعليا نقوم بالسؤال عن undefined.size
و التي هي بالتأكيد غير صحيحة و غير صالحة و ستقوم بإرجاع error مشابه ل Cannot read property "size" of undefined
.
- ماهو الناتج؟
let c = { greeting: "Hey!" };
let d;
d = c;
c.greeting = "Hello";
console.log(d.greeting);
- A:
Hello
- B:
Hey
- C:
undefined
- D:
ReferenceError
- E:
TypeError
الإجابة
في لغة الجافاسكريبت, جميع ال objectsيتم التفاعل معها عن طريق reference و ذلك عندما نقوم بمساواتهم ببعضهم البعض بعلامة ال=.
أولا, المتغير c
يحمل قيمة ل object. لاحقا قمنا بإضافة d
لنفس الrefence الذي لدى المتغير c
لل object.
لذا, عندما تقوم بتغيير object واحد , انت فعليا تقوم بتغيير جميع الobjects.
- ماهو الناتج؟
let a = 3;
let b = new Number(3);
let c = 3;
console.log(a == b);
console.log(a === b);
console.log(b === c);
- A:
true
false
true
- B:
false
false
true
- C:
true
false
false
- D:
false
true
true
الإجابة
new Number()
هي دالة من نوع built-in function constructer. على الرغم من أنها تبدو كرقم, ولكنها في الحقيقة ليس رقم, هي عبارة عن object ولديها العديد العديد من المميزات.
عندما نقوم بإستخدام العلامة او العامل ==
, هي تقوم فقط بالتحقق من إذا ماكان لديها same value.كلا الطرفين قيمتهم تساوي 3
لهذا تقوم بإرجاع true
.
و لكن على الرغم من هذا, عندما نقوم بإستخدام العملية أو المعامل ===
, كلا القيمة and النوع يجب ان يكونا نفس الشيء.
هي ليست new Number()
هي ليست عبارة عن رقم, هي عبارة عن object , وكلاهما سيقومان بإرجاع false.
- ماهو الناتج؟
class Chameleon {
static colorChange(newColor) {
this.newColor = newColor;
return this.newColor;
}
constructor({ newColor = "green" } = {}) {
this.newColor = newColor;
}
}
const freddie = new Chameleon({ newColor: "purple" });
console.log(freddie.colorChange("orange"));
- A:
orange
- B:
purple
- C:
green
- D:
TypeError
الإجابة
الدالة colorChange
هي دالة static, و الدوال التي هي من نوع static هي دوال صممت لكي يتم استخدامها فقط في الconstructor الذي تم تعريفها به, و ليس من الممكن ان يتم تمريرها او استخدامها من قبل اي مكون children. بما أن freddie
هي متغير children فإن الدالة لم يتم تمريرها اليه و هي غير متوفرة في ال instant من freddie
لذا نتحصل على الخطأ TypeError
.
- ماهو الناتج؟
let greeting;
greetign = {}; // Typo!
console.log(greetign);
- A:
{}
- B:
ReferenceError: greetign is not defined
- C:
undefined
الإجابة
تقوم بعمل log على الconsole ل object. و لأننا قمنا بإنشاء object فارغ في global object! عندما قمنا بالخطأ بطباعة greetign
بدل ان نقوم بطباعتها بصورة صحيحة هكذا greeting
, هنا قام مترجم الجافاسكريبت بترجمة الآتي global.greetign = {}
أو window.greetign = {}
في المتصفح.
لكي نتجنب حدوث مثل هذه الحالة, بإمكاننا إستخدام "use strict"
. بفعل هذه الخطوة ستتأكد من أنك قد عرفت المتغير قبل ان تساويه بأي شي آخر.
- ما الذي يحدث عندما نقوم بعمل الآتي؟
function bark() {
console.log("Woof!");
}
bark.animal = "dog";
- A: Nothing, this is totally fine!
- B:
SyntaxError
. You cannot add properties to a function this way. - C:
undefined
- D:
ReferenceError
الإجابة
هذا ممكن في لغة الجافاسكريبت, لأن الدوال هي عبارة عن objects, (كل شيء بداخل الأنواع التي هي primitive هو عبارة عن object)
الدالة هي عبارة عن نوع خاص من الobjects, الكود الذي تقوم بكتابته بنفسك هو ليس بالدالة الفعلية, الدالة هي object لديه خصائص. و هذه الخاصية قابلة للمناداة
- ماهو الناتج؟
function Person(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
const member = new Person("Lydia", "Hallie");
Person.getFullName = function() {
return `${this.firstName} ${this.lastName}`;
};
console.log(member.getFullName());
- A:
TypeError
- B:
SyntaxError
- C:
Lydia Hallie
- D:
undefined
undefined
الإجابة
ليس بإمكانك اضافة الخصائص ل constructor كما تقوم بإضافة الخصائص للobjects. إذا أردت أن تضيف مميزات لكل الobjects مرة واحدة, سيجب عليك أن تقوم بإستخدام الprototype. لذا في هذه الحالة,
Person.prototype.getFullName = function() {
return `${this.firstName} ${this.lastName}`;
};
اذا استطعنا جعل member.getFullName()
تعمل. لماذا ستكون ذات فائدة؟ فلنفترض أننا أضفنا هذه الmethod للconstructor نفسها. ربما ليس أي instance من Person
تحتاج الى هذه ال method. بهذه الطريقة سنقوم بإستهلاك مساحة كبيرة من الذاكرة, بما أنهم سيظلون يحتفظون ب هذه الخاصية, و التي بدورها ستقوم بحجز مساحة في الذاكرة لأي instance. لذا من الأفضل أن نقوم بإضافتهاالى الprototype, بهذه الطريقة ستقوم بحجز مكان واحد فقط في الذاكرة, و لكنها متاحة للكل للوصول إليها.
- ماهو الناتج؟
function Person(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
const lydia = new Person("Lydia", "Hallie");
const sarah = Person("Sarah", "Smith");
console.log(lydia);
console.log(sarah);
- A:
Person {firstName: "Lydia", lastName: "Hallie"}
andundefined
- B:
Person {firstName: "Lydia", lastName: "Hallie"}
andPerson {firstName: "Sarah", lastName: "Smith"}
- C:
Person {firstName: "Lydia", lastName: "Hallie"}
and{}
- D:
Person {firstName: "Lydia", lastName: "Hallie"}
andReferenceError
الإجابة
للمتغير sarah
لم نقم بإستخدام الكلمة المفتاحية new
, عندإستخدام الكلمة المفتاحية new
ف هي تشير الى ال object الخالي او الفارغ الذي قمنا بإنشاءه, و لكن اذا لم تقم بإضافةnew
ف هي ستشير الى ال global object!.
نحن نقول بأن this.firstName
تساوي "Sarah"
و this.lastName
تساوي "Smith"
. ماقمنا بفعله حقا هنا, هو أنه قمنا بتعريف global.firstName = 'Sarah'
و global.lastName = 'Smith'
. المتغير sarah
لا يظل undefined
.
- A: Target > Capturing > Bubbling
- B: Bubbling > Target > Capturing
- C: Target > Bubbling > Capturing
- D: Capturing > Target > Bubbling
الإجابة
- A: true
- B: false
الإجابة
جميع الobjects لديها prototypes, عدا ال objects من نوع base object. الobject من نوع base object هو عبارة عن object تم إنشاءه من قبل المستخدم, أو تم إنشاءه عن طريق إستخدام الكلمة المفتاحية new
. الbase object لديه حق الوصول الى بعض ال methods و الخصائص. مثال: .toString
. هذا هو السبب الذي يمكنك من إستخدام built-in JavaScript methods, مثل هذه ال methods جميعها متاحة في ال ptototype, على الرغم من أن لغة الجافا سكريبت ليس بإمكانها أن تجدها بصورة مباشرة من الobject الذي قمت أنت بإنشاءه, و لكنها تذهب الى سلسلة الprototype حيث بإمكانها ان تجده هناك, مما يجعله قابل للوصول من قبلك, أي بإمكانك أن تصل إليه.
- ماهو الناتج؟
function sum(a, b) {
return a + b;
}
sum(1, "2");
- A:
NaN
- B:
TypeError
- C:
"12"
- D:
3
الإجابة
لغة الجافاسكريبت هي لغة dynamically typed language بمعنى أننا لا نقوم بتعريف نوع معين للمتغيرات, المتغيرات بصورة أوتوماتيكية يتم تحويلها الى أنواع أخرى بدون أن تعرف أنت ذلك, وهذا يسمى ب implicit type coercion. Coercion تعني بأنك تقوم بالتحويل من نوع الى آخر.
في هذا المثال, لغة الجافاسكريبت تقوم بتحويل الرقم 1
الى string, لكي تستطيع الدالةأن تقوم بعملها و تتمكن من إرجاع قيمة. أثناء قيام عملية إضافةالمتغير من النوع number و الذي هو (1
) و المتغير من النوع string والذي هو ('2'
), الرقم تم التعامل معه ك string, بهذه الطريقة سنتمكن من عمل عملية concatenate للمتغيرين من نوع string ك مثال "Hello" + "World"
, لهذا مايحدث هنا هو عبارة عن "1" + "2"
و الذي بدوره يقوم بإرجاع "12"
.
- ماهو الناتج؟
let number = 0;
console.log(number++);
console.log(++number);
console.log(number);
- A:
1
1
2
- B:
1
2
2
- C:
0
2
2
- D:
0
1
2
الإجابة
ال postfix العامل الأحادي ++
:
- تقوم بإرجاع القيمة (هذه ترجع
0
) - تقوم بزيادةالقيمة (number الآن تساوي
1
)
ال prefix العامل الأحادي ++
:
- تقوم بزيادة القيمة(number الآن تساوي
2
) - تقوم بإٍرجاع القيمة (هذه ترجع
2
)
هذا يقوم بإرجاع 0 2 2
.
17.ماهو الناتج؟
function getPersonInfo(one, two, three) {
console.log(one);
console.log(two);
console.log(three);
}
const person = "Lydia";
const age = 21;
getPersonInfo`${person} is ${age} years old`;
- A:
"Lydia"
21
["", " is ", " years old"]
- B:
["", " is ", " years old"]
"Lydia"
21
- C:
"Lydia"
["", " is ", " years old"]
21
الإجابة
اذا قمت بإستخدام tagged template literals, فإن قيمة ال argument الأول هي دائما عبارة عن array والذي نوع قيمها عبارة عن string, ماتبقى من الarguments تتحصل على القيم من الpassed expressions.
- ماهو الناتج؟
function checkAge(data) {
if (data === { age: 18 }) {
console.log("You are an adult!");
} else if (data == { age: 18 }) {
console.log("You are still an adult.");
} else {
console.log(`Hmm.. You don't have an age I guess`);
}
}
checkAge({ age: 18 });
- A:
You are an adult!
- B:
You are still an adult.
- C:
Hmm.. You don't have an age I guess
الإجابة
عندما نقوم بإختبار المساواة أو التساوي بين طرفين, ال primitives يتم مقارنتها عن طريق قيمها, بينما ال objects يتم مقارنتها عن طريق الreference الذي يتبع لها, لغة الجافاسكريبت تتحقق عن إذا ماكان الrefrence الذي يتبع لobject يشير الى نفس الموقع في الذاكرة.
لدينا هنا اثنان من ال objects والتي نقوم بعمل مقارنة بينهما, واللذان بدورهما ليس لديهما ذلك, الobject الذي قمنا بتمريره ك parameter يشير الى موقع مختلف في الذاكرة من الموقع الذي يشير اليه الobject الثاني و الذي تم استخدامه للتحق من شرط المساواة.
لهذا كلا من { age: 18 } === { age: 18 }
و { age: 18 } == { age: 18 }
يرجعان false
.
- ماهو الناتج؟
function getAge(...args) {
console.log(typeof args);
}
getAge(21);
- A:
"number"
- B:
"array"
- C:
"object"
- D:
"NaN"
الإجابة
العامل spread ...args
يقوم بإرجاع array مع arguments. الarray هي object, لذا فإن typeof args
تقوم بإرجاع "object"
.
- ماهو الناتج؟
function getAge() {
"use strict";
age = 21;
console.log(age);
}
getAge();
- A:
21
- B:
undefined
- C:
ReferenceError
- D:
TypeError
الإجابة
بإستخدام "use strict"
, يمكنك التأكد بأنك لن تقوم عن طريق الخطأ بتعريف global variables. نحن لم نقم قط بتعريف المتغير age
, و بما أننا قمنا بإستخدام "use strict"
ستقوم بإرجاع reference error. اذا لم نقم بإستخدام "use strict"
لكانت قد أدت المطلوب, بما أن الخاصية age
تم إضافتها لل global object.
const sum = eval("10*10+5");
- A:
105
- B:
"105"
- C:
TypeError
- D:
"10*10+5"
الأجابة
eval
تقوم بتقييم الكود الذي تم تمريره ك string. إذا كان عبارة عن expression كما في هذه الحالة, فإنها تقوم بتقييم ال expression. ال expression هو 10 * 10 + 5
. و هذا بدوره يقوم بإرجاع الرقم 105
.
sessionStorage.setItem("cool_secret", 123);
A - الى الأبد, فالبيانات لايمكن أن تفقد.
B - عندما يقوم المستخدم بقفل ال tab.
C - عندما يقوم المستخدم بقفل نافذه المتصفح , ليس فقط الtab.
D - عندما يقوم المستخدم بقفل جهاز الكمبيوتر.
الإجابة
البيانات التي يتم تخزينها في sessionStorage
يتم فقدها بعد قفل ال tab.
إذا قمت بإستخدام localStorage
, البيانات ستكون مخزنة هناك الى الأبد, و لكن اذا قمت بإستثناء ان تقوم بمناداة الدالة Clear كما في التالي localStorage.clear()
عندها ستفقد هذه البيانات.:
- ماهو الناتج؟
var num = 8;
var num = 10;
console.log(num);
- A:
8
- B:
10
- C:
SyntaxError
- D:
ReferenceError
الإجابة
مع الكلمة المفتاحية var
بإمكانك تريف عدد من المتغيرات تحمل نفس الإسم, و المتغير سيقوم بأخذ آخر قيمة تمت إضافتها اليه.
ليس بإمكانك أن تفعل هذا مع let
أو const
بما أن الكلمتان المفتاحيتان عبارة عن block-scoped, بمعنى أن القيمة ستكون متاحة في نطاق الBlock الذي تم تعريفها به.
- ماهو الناتج؟
const obj = { 1: "a", 2: "b", 3: "c" };
const set = new Set([1, 2, 3, 4, 5]);
obj.hasOwnProperty("1");
obj.hasOwnProperty(1);
set.has("1");
set.has(1);
- A:
false
true
false
true
- B:
false
true
true
true
- C:
true
true
false
true
- D:
true
true
true
true
الإجابة
كل مفاتيح ال object (عدا الSymbols)هي عبارة عن strings وراء الكواليس, حتى لو لم تقم بكتابة ذلك صراحة بنفسك ك string, لهذا دائما obj.hasOwnProperty('1')
تقوم بإرجاع القيمة true.
ولكنها لا تعمل بهذا الشكل مع set, ليس هنالك '1'
من ضمن set, لهذا set.has('1')
تقوم بإرجاع false
, لديها القيمة الرقمية 1
أي من النوع number, set.has(1)
تقوم بإرجاع true
.
- ماهو الناتج؟
const obj = { a: "one", b: "two", a: "three" };
console.log(obj);
- A:
{ a: "one", b: "two" }
- B:
{ b: "two", a: "three" }
- C:
{ a: "three", b: "two" }
- D:
SyntaxError
الإجابة
إذا كان لديك مفتاحان يحملان نفس الاسم, فإن المفتاح سيتم تبديله, سيكون المفتاح في نفس مكانه, ولكنه سيحمل فقط القيمة الأخيرة
- A: true
- B: false
- C: تعتمد على
الإجابة
سياق التنفيذ الأساسي هو سياق تنفيذ الglobal, وهي الشيء الذي يمكن الوصول إليه من أي مكان في الكود الذي ببرنامجك.
- ماهو الناتج؟
for (let i = 1; i < 5; i++) {
if (i === 3) continue;
console.log(i);
}
- A:
1
2
- B:
1
2
3
- C:
1
2
4
- D:
1
3
4
الإجابة
العبارة continue
تقوم بتخطي دورة التكرار إذا وجد شرط معين يقوم بإرجاع true
.
- ماهو الناتج؟
String.prototype.giveLydiaPizza = () => {
return "Just give Lydia pizza already!";
};
const name = "Lydia";
name.giveLydiaPizza();
- A:
"Just give Lydia pizza already!"
- B:
TypeError: not a function
- C:
SyntaxError
- D:
undefined
الإجابة
String
هي built-in constructor, و لهذا سنتمكن من إضافة خصائص لها. لقد قمت بإضافة method للprototype الخاص ب String
. Primitive strings يتمتحويلهم بصورة اوتوماتيكية الى objects من نوع string, و التي بدورها تم انشائها عن طريق دالة ال string prototype, لهذا جميع الstrings و التي هي string objects لديها حق الوصول الى الmethod.
- ماهو الناتج؟
const a = {};
const b = { key: "b" };
const c = { key: "c" };
a[b] = 123;
a[c] = 456;
console.log(a[b]);
- A:
123
- B:
456
- C:
undefined
- D:
ReferenceError
الإجابة
مفاتيح ال object يتم تحويلها اوتوماتيكيا الى strings. نحن نحاول أن نقوم بجعل object عبارة عن مفتاح للobject a
, و الذي يحمل القيمة 123
.
و لكن, عندما نقوم بمحاول جعل object الى نوع string, سيصبح "[Object object]"
. لذا ما نحاول أن نقوله هنا, هو أن a["Object object"] = 123
.
إذا, سنحاول أن نفعل هذا مرة أخرى , c
هو object آخر سنقوم بتحويله الى string بصورة صريحة, لذا a["Object object"] = 456
.
إذاَ, نحن نقوم بعمل log ل a[b]
, و التي هي في الحقيقة a["Object object"]
. و نحن قبل قليل قمنا بوضع قيمتها التي تساوي 456
, لذا ستقوم بإرجاع 456
.
- ماهو الناتج؟
const foo = () => console.log("First");
const bar = () => setTimeout(() => console.log("Second"));
const baz = () => console.log("Third");
bar();
foo();
baz();
- A:
First
Second
Third
- B:
First
Third
Second
- C:
Second
First
Third
- D:
Second
Third
First
الإجابة
لدينا الدالة 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.
<div onclick="console.log('first div')">
<div onclick="console.log('second div')">
<button onclick="console.log('button')">
Click!
</button>
</div>
</div>
- A: الخارجي
div
- B: الداخلي
div
- C:
button
- D: array تحتوي على جميع العناصرالمتداخلة.
الإجابة
العنصر المتداخل الأعمق الذي تسبب بتنفيذ الevent هو العنصر الذي يستهدفه هذا الevent, بإمكانك إيقاف ال bubbling عن طريق event.stopPropagation
.
<div onclick="console.log('div')">
<p onclick="console.log('p')">
Click here!
</p>
</div>
- A:
p
div
- B:
div
p
- C:
p
- D:
div
الإجابة
إذا قمنا بالضغط على p
سنرى إثنان من الlogs, ألا و هما p
و div
, أثناء عملية event propagation, هنالك ثلاث مراحل: الا وهي capturing, target و bubbling. بصورة افتراضية, الevent handlers يتم تنفيذهم في مرحلة الbubbling (إلا في حال أنك قمت بضبط قيمة useCapture
ل true
). هي تتسلسل ابتداءا من أعمق عنصر متداخل تصاعدا الى الأقل عمقاً.
- ماهو الناتج؟
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
الإجابة
في الحالتين, بإمكاننا تمرير ال object الذي نود أن تشير اليه الكلمة المفتاحية this
, ولكن, .call
هي أيضا تم تنفيذها حالا.
.bind.
تقوم بإرجاع نسخة من الدالة, ولكن مع سياق محدد, لذا هي لا يتم تنفيذها حالاً.
- ماهو الناتج؟
function sayHi() {
return (() => 0)();
}
console.log(typeof sayHi());
- A:
"object"
- B:
"number"
- C:
"function"
- D:
"undefined"
الإجابة
دالة sayHi
تقوم بإرجاع القيمة المرجعة من الدالة المناداة في اللحظة (IIFE). هذه الدالة تقوم بإرجاع 0
, و الذي نوعه عبارة عن "number"
.
لمعلوماتك: لدينا فقط سبعة أنواع من ال built-in و هي : null
, undefined
, boolean
, number
, string
, object
, و symbol
."function"
هي ليست نوع, وبما أن الدوال عبارة عن objects, ف هي ليست من النوع "object"
.
- أي هذه القيم هي قيم خطئية؟
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: جميعها
الإجابة
لدينا فقط ستة قيم خطئية:
undefined
null
NaN
0
''
(empty string)false
Function constructors, مثل new Number
و new Boolean
هي قيم صحيحية.
- ماهو الناتج؟
console.log(typeof typeof 1);
- A:
"number"
- B:
"string"
- C:
"object"
- D:
"undefined"
الإجابة
typeof 1
تقوم بإرجاع "number"
.
typeof "number"
تقوم بإرجاع "string"
- ماهو الناتج؟
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
الإجابة
عندما تقوم بضبط قيمة ما لعنصر في الarray , و بعد إضافة هذا العنصر انت تكون قد تجاوزت طول الarray, لغة الجافاسكريبت تنشيء شيئا يسمى ب "empty slots", أي خانة فارغة, و هي في الحقيقة تحمل القيمة undefined
, و لكنك سترى شيئا كالتالي:
[1, 2, 3, 7 x empty, 11]
وذلك يعتمد على المكان الذي قمت فيه بتشغيل البرنامج ( هو مختلف لكل متصفح, node, ...الخ)
- ماهو الناتج؟
(() => {
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
الإجابة
النطاق أو ال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
.
- كل شيء في الجافاسكريبت هو عبارة عن ...
- A: primitive أو object
- B: function أو object
- C: فقط objects , سؤال مخادع
- D: number or object
الإجابة
لغة الجافاسكريبت لديها فقط 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
تقوم بعمل هذه العملية.
- ماهو الناتج؟
[[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]
الإجابة
[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]
.
- ماهو الناتج؟
!!null;
!!"";
!!1;
- A:
false
true
false
- B:
false
false
true
- C:
false
true
true
- D:
true
true
false
الإجابة
null
قيمة خطئية.
!null
تقوم بإرجاع true
.
!true
تقوم بإرجاع false
.
""
قيمة خطئية.
!""
تقوم بإرجاع true
.
!true
تقوم بإرجاع false
.
1
قيمة صحيحية.
!1
تقوم بإرجاع false
.
!false
تقوم بإرجاع true
.
- ماهو الذي تقوم الدالة
setInterval
بإرجاعه في المتصفح؟
setInterval(() => console.log("Hi"), 1000);
A - رقم فريد أو متفرد id
B - قيمة محددة لل milliseconds
C - الدالة التي تم تمريرها
undefined
- D
الإجابة
تقوم بإرجاع ال id الفريد, هذا الid يمكن استخدامه لكي يقوم بتصفير عداد الفترات المفصلة أي الinterval عن طريق استخدام الدالة clearInterval()
- مالذي يتم ارجاعه بعد تنفيذ الكود أدناه؟
[..."Lydia"];
- A:
["L", "y", "d", "i", "a"]
- B:
["Lydia"]
- C:
[[], "Lydia"]
- D:
[["L", "y", "d", "i", "a"]]
الإجابة
الstring هي تكرارية, و عملية الspread (...) تقوم بتحويل اي حرف تم فيه تنفيذ فئة تكرارية الى عنصر منفرد واحد.
- ماهو الناتج؟
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
الإجابة
الدوال العادية ليس بإمكانها ان تتوقف في وسط التنفيذ بعد أن يتم مناداتها, و لكن الدوال من نوع 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
.
- ما الذي يتم ارجاعه عند تنفيذ الكود؟
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"
الإجابة
عندما نقوم بتمرير عدد من الpromises للدالة Promise.race
. فهي تقوم برفض أو فصل الpromise الاولى. للدالة setTimeout
نحن نقوم بتمرير timer: 500ms لل promise الأولى و التي هي (firstPromise
), و 100ms اي 100ملي ثانية للpromise الثانية والتي هي (secondPromise
) هذا يعني ان ال secondPromise
يتم فصلها اولاً مع القيمة 'two'
. res
الآن تحمل قيمة 'two'
, وهي التي تم طباعتها عن طريق الlog.
- ماهو الناتج؟
let person = { name: "Lydia" };
const members = [person];
person = null;
console.log(members);
- A:
null
- B:
[null]
- C:
[{}]
- D:
[{ name: "Lydia" }]
الإجابة
أولا, نقوم بتعريف المتغير 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.
- ماهو الناتج؟
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]
الإجابة
بإستخدام for-in
التكرارية, بامكاننا أن نصل الى جميع المفاتيح التي تخص object معين. في هذه الحالة name
و age
. ماوراء الكواليس, مفاتيح ال objects هي عبارة عن strings (إذا لم تكن هذه المفاتيح عبارة عن symbol), في أي حلقة من الحلقات التكرارية, نقوم بضبط القيمة item
مساوية للمفتاح الحالي الذي هي تتكرر فيه اوعنده. أولا item
تساوي name
, و يتم طباعتها عن طريق الlog, ثم item
تساوي age
و التي ايضا تم طباعتها عن طريق الlog.
- ماهو الناتج؟
console.log(3 + 4 + "5");
- A:
"345"
- B:
"75"
- C:
12
- D:
"12"
الإجابة
Operator associativity او ترابطية العامل هي الترتيب أو التسلسل الذي يقيم به الcompiler ال expressions, ف هو إما أن يكون من اليسار الى اليمين أو من اليمين الى اليسار. هذا يحدث فقط إذا كان جميع الoperators لديها نفس الأسبقية. لدينا فقط نوع واحد من الoperator ألا و هو +
. بالإضافة الى التالي, الترابطية هي من اليسار الى اليمين.
3 + 4
يتم تقييمها أولا. هذا مايعطينا الناتج الذي هو عبارة عن الرقم 7
.
7 + '5'
تقوم بإرجاع الناتج "75"
بسبب عملية ال coercion وهي العمليةالتي تقوم بالتحويل من نوع الى آخر, لغة الجافاسكريبت تقوم بتحويل الرقم 7
الى النوع string, أنظرالى السؤال رقم 15 في الأعلى. بإمكاننا عمل concatenate لمتغيرين من النوع string بإستخدام العملية +
. "7" + "5"
سترجع الناتج "75"
.
const num = parseInt("7*6", 10);
- A:
42
- B:
"42"
- C:
7
- D:
NaN
الإجابة
فقط الأرقام الأولى في الstring يتم إرجاعها. بناءاً على radix (الargument الثاني لكي يتم تحديدنوعية الرقم الذي نود أن نقوم بعمل parse له الى: base 10, hexadecimal, octal, binary, الخ. ). تقوم parseInt
بالتحقق عن إذا ماكانت الحروف في الstring صالحة. و بمجرد أن تجد حرف غير صالح في ال radix, ف هي تقوم بإيقاف عملية الparsing مباشرة و تتجاهل الحروف التي تليه.
*
ليست رقم صالح. هي فقط تقوم بعمل parse ل "7"
الى عدد عشري 7
. num
الآن تحمل القيمة 7
.
- ماهو الناتج؟
[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 ]
الإجابة
عندما يتم عمل mapping لل array, فإن قيمة num
ستساوي قيمة العنصر الذي يتم حاليا المرور به, فكما نعرف أن الmapping يدور على جميع عناصر الarray. في هذه الحالة, العناصر عبارة عن أرقام, لهذا فإن شرط ال if statement typeof num === "number"
يقوم بإرجاع true
. دالة map تقوم بإنشاء array جديدة, و إدخال القيم المرجعة من الدالة في هذه الarray.
ولكن, لا نقوم بإرجاع قيمة. عندما لا نقوم بإرجاع قيمة من الدالة, فإن الدالة تقوم بإرجاع undefined
. لكل عنصرٍ في الarray, فإن نطاق الدالة او نعني الfunction block يتم مناداته, لهذا لأي عنصر نقوم بإرجاع undefined
.
- ماهو الناتج؟
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"
الإجابة
ال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"
.
- ماهو الناتج؟
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!
الإجابة
مع عبارة 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'
.
- ماهو الناتج؟
function Car() {
this.make = "Lamborghini";
return { make: "Maserati" };
}
const myCar = new Car();
console.log(myCar.make);
- A:
"Lamborghini"
- B:
"Maserati"
- C:
ReferenceError
- D:
TypeError
الإجابة
عندما تقوم بإرجاع خاصية, فإن قيمة هذه الخاصية هي تساوي القيمة المرجعة, ليس القيمة التي تم ضبطها في دالة الconstructor. نقوم بإرجاع ال string "Maserati"
, لذا فإن myCar.make
تساوي "Maserati"
.
- ماهو الناتج؟
(() => {
let x = (y = 10);
})();
console.log(typeof x);
console.log(typeof y);
- A:
"undefined", "number"
- B:
"number", "number"
- C:
"object", "number"
- D:
"number", "undefined"
الإجابة
let x = y = 10;
هي في الحقيقة إختصار ل:
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"
.
- ماهو الناتج؟
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
الإجابة
بإمكاننا مسح خصائص object معين عن طريق استخدام الكلمة المفتاحية delete
, أيضا يمكن فعل هذا في ال prototype. بمسح خاصية معينة من الprototype, فهي سيتم مسحها وبالتالي لن تكون موجودة في سلسلة الprototype. في هذه الحالة فإن الدالة bark
لن تكون موجودة بعد الآن في الprototype بعد delete Dog.prototype.bark
, ولكن بالرغم من هذا فنحن نحاول الوصول إليها.
عندما نحاول أن ننادي شيئا ما في دالة و هو ليس موجود في هذه الدالة, فإننا سنتحصل على الخطأ TypeError
, و في هذه الحالة TypeError: pet.bark is not a function
بما أن pet.bark
هي undefined
.
- ماهو الناتج؟
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}
الإجابة
ال object Set
هو مجموعة من القيم الفريدة, أي القيمة بإمكانها أن تتواجد مرة واحدة فقط في المجموعة.
نقوم بتمرير التكراري أي نعني الiterable [1, 1, 2, 3, 4]
بوجود قيمة مكررة ألا وهي 1
. بما أننا لا يمكن أن نضع قيمة واحدة مرتين في مجموعة, فإن واحدة من القيم المكررة سيتم إزالتها, و سيكون الناتج: {1, 2, 3, 4}
.
- ماهو الناتج؟
// counter.js
let counter = 10;
export default counter;
// index.js
import myCounter from "./counter";
myCounter += 1;
console.log(myCounter);
- A:
10
- B:
11
- C:
Error
- D:
NaN
الإجابة
هنا يوجد لدينا module مستورد وهو قابل للقراءة فقط, ليس بإمكانك تعديل او تحديث الmodule المستورد, أي imported module. فقط الmodule الذي قام بتصديره هو القادر على تغيير قيمته.
عندما نحاول أن نزيد قيمة المتغير myCounter
, سنتحصل على الخطأ myCounter
هو قابل للقراءة فقط و ليس من الممكن تعديله.
- ماهو الناتج؟
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
الإجابة
العامل delete
تقوم بإرجاع قيمة boolen و هي true
عندما تتم عملية المسح بنجاح, خلاف ذلك ستقوم بإرجاع false
, ولكن المتغيرات المعرفة بالكلمات المفتاحية var
, const
أو let
ليس بالإمكان مسحها بإستخدام العامل delete
.
المتغير name
تم تعريفه باستخدام الكلمة المفتاحية const
, لهذا فإن عملية مسحه لم تتم بنجاح, وتم إرجاع القيمة false
, عندما نقوم بضبط المتغير age
ليساوي القيمة 21
فإننا فعليا نقوم بإضافة خاصية تسمى age
للglobal object. بإمكانك أن تمسح خصائص من الobjects بنجاح بإستخدام هذه الطريقة , أيضا الglobal objects, لذا فإن delete age
تقوم بإرجاع true
.
- ماهو الناتج؟
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]
الإجابة
بإمكاننا إستخراج أو استخلاص القيم من arrays أو من objects عن طريق إستخدام الdestructing, على سبيل المثال:
[a, b] = [1, 2];
[y] = [1, 2, 3, 4, 5];
- ماهو الناتج؟
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 }
الإجابة
من الممكن دمج الobjects بإستخدام العامل spread ...
. هي تمكنك من إنشاء نسخ من أزواج ال key/value أي أزواج المفاتيح و القيم التي تنتمي الى object معين, و إضافتهم الى object آخر. في هذه الحالة, نحن نقوم بعمل نسخ من الobject user
, و من ثم إضافتهم الى ال obejct admin
. ال object admin
الآن يتضمن نسخ عبارة عن أزواج مفاتيح و قيم, و هذا ما سبب في إعطاء النتيجة { admin: true, name: "Lydia", age: 21 }
.
- ماهو الناتج؟
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"]
الإجابة
مع إستخدام defineProperty
method, بإمكاننا إضافة خصائص جديدة لobject معين,أو تعديل خصائصه الحالية,. عندما نقوم بإضافة خاصية لobject بإستخدام defineProperty
method, ف هي بطبيعة الحال ليست enumerable. ال Object.keys
method تقوم بإرجاع جميع أسامي الخصائص من object معين و التي هي جميعها enumerable, في هذه الحالة "name"
فقط.
الخصائص التي تم إضافتها بإستخدام defineProperty
method هي بطبيعة الحال غير قابلة للتغيير أو التعديل. بإمكانك عمل override بإستخدام الخصائص writable
, configurable
و enumerable
. بهذه الطريقة, ال defineProperty
method ستعطيك تحكم أكثر بكثير على الخصائص التي قمت بإضافتها الى object معين.
- ماهو الناتج؟
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}"
الإجابة
ال 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.
- ماهو الناتج؟
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
الإجابة
العامل الأحادي ++
يقوم أولا بإرجاع قيمة المعامل, ثم يقوم بزيادة قيمة هذا المعامل. قيمة num1
تساوي 10
, و بما أن دالة increaseNumber
أولا تقوم بإرجاع قيمة num
و التي هي تساوي 10
, و تقوم بزيادة قيمة num
لاحقاً فقط.
num2
تساوي10
, وبما أننا نقوم بتمرير num1
ل increasePassedNumber
. فإن number
تساوي 10
والتي هي قيمةnum1
. مجدداً, العامل الأحادي ++
, أولاً يقوم بإرجاع قيمة المعامل, و من ثم زيادة قيمة المعامل. قيمة number
تساوي10
, إذاً num2
تساوي 10
.