Nilz
Nilz
خواندن ۱۰ دقیقه·۳ سال پیش

123 سوال ضروری در مصاحبه جاوااسکریپت- قسمت دوم

14- خروجی کد زیر چیست؟

var bar = true; console.log(bar + 0); console.log(bar + &quotxyz&quot); console.log(bar + true); console.log(bar + false);

عملگر + دو تا کار می‌کنه: یا عمل جمع ریاضی یا عمل concatenation (الحاق)

جمع ریاضی:

// Number + Number -> addition 1 + 2 // 3 // Boolean + Number -> addition true + 1 // 2 / Boolean + Boolean -> addition false + false // 0

الحاق رشته‌:

// String + String -> concatenation 'foo' + 'bar' // &quotfoobar&quot // Number + String -> concatenation 5 + 'foo' // &quot5foo&quot // String + Boolean -> concatenation 'foo' + false // &quotfoofalse&quot

جواب سوال واضحه دیگ:)

پ.ن: البته منظور اینجا عملگر باینری + هست.


15- خروجی کد زیر چیست؟

var z = 1, y = z = typeof y; console.log(y);

عملگر = یا assignment

اولا = مثل سایر عملگر‌های دیگ، یک عملگر محسوب میشه که تو جدول precedence، اولویت پایینی داره. به خاطر همینه که تو دستور x=2*2+1، اول عملیات محاسباتی انجام میشه بعد عملگر = میاد مقدار نهایی رو میریزه تو متغیر x.

مثل سایر عملگرهای دیگ یک مقدار خروجی داره. مثلا اول دستور بالا خروجیش 5 هست که میریزه تو متغیر x.

Chain assignments

یه ویژگی جالبی = داره chain assignments هستش:

let a, b, c; a = b = c = 2 + 2; console.log( a ); // 4 console.log( b ); // 4 console.log( c ); // 4

این عملیات chain assignment از راست به چپ میره جلو! مثلا این‌جا اول راست‌ترین expression یعنی 2+2 انجام میشه، بعد مقدارش به ترتیب در c بعد در b و در a ریخته میشه!

حالا جواب سوال: undefined.

گفتیم که ترتیب کار از راست به چپ هست و تو این مثال ترتیب کار به این صورته:

var z; z = 1; var y; z = typeof y; y = z;

پس اول typeof y انجام میشه و ازونجایی که هنوز مقداردهی نشده، تایپش undefined هستش. پس مقدار undefined اول در z ریخته میشه و مقدار درون z در y ریخته میشه.


16- خروجی کد زیر چیست؟

var foo = function bar() { return 12; }; typeof bar();

میدونیم که در جاوااسکریپت، تابع یک مقدار محسوب میشه که مثل هر مقدار دیگ‌ای نوع داره و نوع تابع در جی‌اس: object هستش و ما نه‌تنها میتونیم صداشون بزنیم بلکه می‌تونیم به عنوان شی باهاشون رفتار کنیم: بهشون پراپرتی اضافه کنیم یا ازشون حذف کنیم و ...

مثلا یکی از پراپرتی‌هایی که تابع داره name هستش:

//function declaration function sayHi(){ console.log(&quotHi&quot); } console.log(sayHi.name); //sayHi //Function expression let sayHello = function() { console.log(&quotHello&quot); }; console.log(sayHello.name); //sayHello

Named Function NFE)

این یکی از روش‌های تعریف تابع محسوب میشه:

//function expression let sayHello = function() { console.log(&quotHello&quot); };

حالا اگر به function expression اسم اضافه کنیم میشه NFE:

//Name Function Expression let sayHello = function func() { console.log(&quotHello&quot); };

حالا تفاوت بین این‌ دو تا چیه؟ یک. توجه داشته باشید که این روش تعریف، همچنان function expression محسوب میشه و اضافه‌شدن یک اسم بعد از function اون رو به یک function declaration تبدیل نمی‌کنه.

دو. این تابع همچنان با نام sayHello از بیرون تابع، قابل دسترسه:

sayHello() //output: &quothello&quot

اما چه چیزی، NFE رو متفاوت می‌کنه؟

  1. به تابع اجازه میده که خودش، به خودش ارجاع بده.
  2. و این اسم بیرون از اسکوپ خود تابع، قابل دسترس نیست.

به طور مثال:

let sayHello = function func(name) { if (name) { return console.log(`hello ${name}`); } func(&quotGuest&quot); }; sayHello(); //hello Guest console.log(func.name); //ReferenceError: func is not defined

همانطور که بالا دیدین: از بیرون نمیشه به تابع func دسترسی داشته باشیم ولی از داخل خود تابع میشه.

جواب سوال: ReferenceError: bar is not defined.


17.1- تفاوت بین تعریف تابع به دو صورت زیر چیست؟

//function expression var foo = function(a,b) { // Some code }


function declaration function bar () { // Some code }

این دو مدل تعریف تابع بسیار سینتکس مشابهی دارند. یکی از بزرگ‌ترین تفاوتی که بین‌شون وجود داره اسم تابع هستش که در روش function expression، میتونه حذف بشه تا بشه یک تابع ناشناس تعریف کنیم. function expression میتونه به عنوان IIFE استفاده بشه، که دقیقا زمانی که تعریف میشه، اجرا میشه.

تفاوت دیگری که بین این دو روش وجود داره، در مفهومی به نام hoisting هستش:

JavaScript Hoisting refers to the process whereby the interpreter allocates memory for variable and function declarations prior to execution of the code.

کلمه hoisting به فارسی به معنی بالا بردن، بلند کردن، به کمک طناب بالا کشیدن هستش. در جاوااسکریپت، hoisting به فرایندی اشاره می‌کنه که درش، مفسر برای variable declarations و function declarations قبل از مرحله اجرا، فضایی رو تخصیص میده. اگر declaration با کلمه کلیدی var انجام بشه، به طور پیش فرض با مقدار undefined مقداردهی اولیه میشه! اما اگر با کلمه کلیدی let و const اعلام بشه، وارد فرایند hoisting نمیشه.

معمولا، hoisting رو این‌طوری نشون میدن که انگار مفسر میاد declaration و مقداردهی اولی متغیر و تابع رو بر‌میداره و در بالای کد قرار میده. در صورتی که تا زمانی که اون خط کد اجرا نشده، مقداردهی متغیر انجام نمیشه.

//function declaration function catName(name) { console.log(&quotMy cat's name is &quot + name); } catName(&quotTiger&quot); /*The result of the code above is: &quotMy cat's name is Tiger&quot*/

کد بالا دقیقا طوری نوشته شده که انتظار میره نوشته بشه، اول تابع رو تعریف میکنیم بعد صداش می‌کنیم. اما چه اتفاقی می‌افته اگر قبل از تعریف تابع، صداش بزنیم؟

catName(&quotTiger&quot); //function declaration function catName(name) { console.log(&quotMy cat's name is &quot + name); } /*The result of the code above is: &quotMy cat's name is Tiger&quot*/

کد هنوز کار کرده و این به‌خاطر hoisting هستش.

Only declarations are hoisted

جاواسکریپت، فقط عمل declaration رو hoisting می‌کنه، نه مقدار دهی اولیه رو!

console.log(num); // Returns 'undefined' from hoisted var declaration (not 6) var num; // Declaration num = 6; // Initialization

درسته متغیر num با var اعلام شده و وارد مرحله hoisting شده، ولی چون قبل از مقدار دهی اولیه، ازش استفاده، به طور پیش فرض با مقدار undefined، مقداردهی میشه.


خوب حالا بریم سراغ ادمه جواب سوال:

در جاوااسکریپت، function expression برخلاف function declaration، وارد مرحله hoisting نمیشن. شما نمیتونی از function expression استفاده کنی قبل ازین‌که ایجادشون کنی:

console.log(notHoisted) // undefined // even though the variable name is hoisted, the definition isn't. so it's undefined. notHoisted(); // TypeError: notHoisted is not a function var notHoisted = function() { console.log('bar'); };

اول notHoiseted به عنوان یک متغیر اعلام میشه و hoisted میشه، و به طور پیش فرض با undefined مقدار‌دهی میشه، ولی هنوز نمیشه به عنوان تابع ازش استفاده کرد چون همانطور که گفتیم عمل مقدار دهی زمانی انجام میشه که تو کد نوشته شده!


17.2- خروجی کد زیر چیست؟

bar(); (function abc(){console.log('something')})(); function bar(){console.log('bar got called')};

جواب:

bar got called something

ازونجایی که تابع bar اول صدا زده شده و همانطور که از سوال قبل متوجه شدیم که declaration functionها hoisted میشن، پس اول bar اجرا میشه و میره سراغ اجرای تابع IIFE.


18. در چه شرایطی، تعریف تابع hoisted نمیشه؟

جواب این سوال در سوال 17.1 به بیان دیگری، داده شده. زمانی که به صورت function expression تابعی رو تعریف کنیم، اون تابع hoisted نمیشه. به طور مثال:

var foo = function foo() { return 12; }

این کد، پشت صحنه این‌جوری تعریف میشه:

var foo = undefined; foo(); // Here foo is undefined foo = function foo() { //* // Some code stuff } foo() // Now foo is defined here.

ترتیب کار به این صورته foo با var تعریف و به صورت پیش‌فرض با undefined مقداردهی میشه (hoisted) میشه. تو خط * تازه مقدار دهی میشه و بعدش میشه ازش به عنوان تابع ازش استفاده کرد. درواقع foo تا قبل از خط * یک متغیره که با مقدار undefined مقدار دهی شده.


19. خروجی کد زیر چیست؟

var salary = &quot1000$&quot (function () { console.log(&quotOriginal salary was &quot + salary); //1 var salary = &quot5000$&quot console.log(&quotMy New Salary &quot + salary); })();

جواب: undefined, 5000$
شاید در نگاه اول انتظار داشته باشیم که تو خط 1، مقدار salary از اسکوپ بیرونی گرفته بشه و مقدارش 1000$ باشه. اما دوباره بحث hoisting میاد بالا به این صورت که:

در داخل خود تابع IIFE، ما یه متغیر salary داریم که با var تعریف شده (hoisted شده)، پس تو خط 1 وقتی داره دنبال متغیر salary میگرده، لازم نیست که بره متغیر رو از اسکوپ بیرونی خودش بگیره، اما چون هنوز مقداردهی نشده، پس مقدار salary به طور پیش فرض با undefinded مقداردهی شده. پس خروجی خط 1 undefined خواهد بود.


20. تفاوت بین typeof و instanceof چیست؟

console.log(typeof 42); // expected output: &quotnumber&quot console.log(typeof 'blubber'); // expected output: &quotstring&quot console.log(typeof true); // expected output: &quotboolean&quot console.log(typeof undeclaredVariable); // expected output: &quotundefined&quot


function Car(make, model, year) { this.make = make; this.model = model; this.year = year; } const auto = new Car('Honda', 'Accord', 1998); console.log(auto instanceof Car); // expected output: true console.log(auto instanceof Object); // expected output: true

دو تا مثال ساده از این دو اپریتور که هر دو از ساید developer.mozilla کپی شده.

شاید به نظر بیاد هر دو این اپریتورها کار یکسانی انجام میدن ولی اون‌ها کار متفاوتی انجام میدن.

اپریتور typeof

این اپریتور برای این استفاده میشه ک ببینی ایا نوع داده مقداری که ب عنوان آپرند بهش می‌دی، یکی از هشت نوع‌داده‌های اصلی هست یا خیر: number, string, boolean, object,function,undefined, symbol, bigInt. خروجی این اپرتور یک رشته است. تو مثال بالا هم میتونین مشاهده بفرمایید:). توجه داشته باشید که نمیتونیم برای بررسی اینکه ایا مقداری null هست یا خیر، ازین اپریتور استفاده کنیم چون به اشتباه object برمی گردونه به خاطر همین بهتره از "===" استفاده کنیم:

console.log( typeof null) //object let a=null; console.log(a === null) // false

ازین اپریتور حتی میشه برای بررسی یک expression هم استفاده بشه:

let foo=1; let bar = &quot1&quot console.log(typeof (foo+bar)) //string

اپریتور instanceof

این اپریتور تست می‌کنه که ایا این اپرند، یکی از نمونه‌ها و یا شی‌های کلاس مورد نظر هست یا خیر. خروجی این اپریتور، یک مقدار boolean هست.

The instanceof operator tests to see if the prototype property of a constructor appears anywhere in the prototype chain of an object.

به بیان دیگر، این اپریتور میاد نگاه می‌کنه ببینه ایا آپرند سمت راستی توی زنجیره پروتوتایپ‌های آپرند سمت چپی قرار داره یا نه! که اگر بود true میفرسته و اگر نبود false.

مثلا تو مثال بالا اگر از شی auto یه کنسول.لاگ بگیریم، خروجی شبیه این میشه:

همانطور که میبینید، شی auto از طریق پروتوتایپش به تابع کانستراکتور Car وصله و خود Car هم از طریق پورتوتایپش به Object متصله.

درنتیجه خروجی هر دو کنسول.لاگ‌ها تو مثال بالا، true هست.

https://levelup.gitconnected.com/comparing-the-javascript-typeof-and-instanceof-operators-8844f23633a#:~:text=The%20typeof%20and%20the%20instanceof,that'll%20always%20return%20true%20.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/typeof

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/instanceof


21. طول ارایه انجمنی (associative) زیر را محاسبه کنید؟

let counterArray={ A:3, B:4 }; counterArray[&quotc&quot]=1

در جاوااسکریپت، ما هم یک ساختار داده ارایه داریم که تشکیل شده از جفت‌‌های ایندکس و داده، یعنی داده‌ها در مکان‌های مشخصی به نام ایندکس ذخیره شده‌اند. در حالی‌که ارایه‌های انجمنی در اصل، همون اشیاء هستند که تشکیل شده از جفت‌های key-value. یعنی تو اینجا داده‌ها (value) با استفاده از keyها قابل دسترس هستند.

طول ارایه‌های انجمنی: برخلاف ارایه معمولی، ارایه‌های انجمنی، پراپرتی length یا طول رو ندارند. به خاطر همین نمیشه این طوری نوشت:

console.log(counterArray.length) //undefined

برای بدست اورن طول این ارایه‌ها باید از روش‌های دیگ استفاده کرده که دوتاش اینجا اورده شده:

روش اول: استفاده از حلقه for...in و پیمایش ارایه و شمردن keyها.

function getLength(object) { var count = 0; for(key in object) { // hasOwnProperty method check own property of object if(object.hasOwnProperty(key)) count++; } return console.log(count); } getLength(counterArray) //3

متد hasOwnProperty درواقع یک مقدار boolean برمیگردونه. اگر ابجکت مورد نظر اون پراپرتی رو داشت true و اگر نداشت false برمی‌گردونه.

روش دوم: استفاده از متد keys.

متد keys ارایه‌ای، تشکیل شده از keyهایِ شیِ داده‌شده بهش رو برمیگردونه.

console.log(Object.keys(counterArray)); //[ 'A', 'B', 'c' ] console.log(Object.keys(counterArray).length); //3

https://www.geeksforgeeks.org/calculate-the-length-of-an-associative-array-using-javascript/


22. تفاوت بین تابع، متد و کانستراکتور چیست؟

اگر با شی‌گرایی اشنایی دارین، حتما میدونید که توابع، متدها و کانستراکتورها سه چیز متفاوت هستند امادر جاوااسکریپت، این‌ها درواقع در نوع کاربردی که دارند، متفاوت هستند:

توابع:

function helloWorld(name) { return &quothello world, &quot + name; } helloWorld(&quotJS Geeks&quot); // &quothello world JS Geeks&quot

متد‌ها: چیزی نیستند جز توابعی که در شی تعریف میشن. یعنی جز پراپرتی‌های اون شی محسوب میشن.

var obj = { helloWorld () { return &quothello world, &quot + this.name; }, name: 'John Carter' } obj.helloWorld(); // &quothello world John Carter&quot

تو مثال بالا، توجه کنید که this در متد helloWorld به خود obj اشاره می‌کنه.

کانستراکتور‌ها:

سومین استفاده‌ای که از توابع میشه، کانستراکتورها هستند.

function Employee(name, age) { this.name = name; this.age = age; } var emp1 = new Employee('John Doe', 28); emp1.name; // &quotJohn Doe&quot emp1.age; // 28

اما اینجا یه تفاوتی وجود داره که کانستراکتورها با اپریتور new صدا زده میشه که میشه باهاش یک شی/نمونه جدید ساخت.

https://github.com/ganqqwerty/123-Essential-JavaScript-Interview-Questions#question-22-difference-between-function-method-and-constructor-calls-in-javascript


jsjavascriptinterview
...
شاید از این پست‌ها خوشتان بیاید