js interview question
هویست چیه ؟
به عملیات بالا بردن مقادیر var, function به ابتدای همون اسکوپ میگن هویست. و let const هویست نمیشن
فرق let, var const چیه؟
منظور از redeclared ساخت مجدد یک متغیر با همون نام هتسش
var foo = 1;
var foo = 2;
console.log(foo); // 2
let baz = 3;
let baz = 4; // Uncaught SyntaxError: Identifier 'baz' has already been declared
جدول مقایسه
Behavior | var | let | const |
---|---|---|---|
Scope | Function or Global | Block | Block |
Initialization | Optional | Optional | Required |
Redeclaration | Yes | No | No |
Reassignment | Yes | Yes | No |
Accessing before declaration | undefined | ReferenceError | ReferenceError |
فرق == و === چیه؟
توی دوتا مساوی سعی میکنه تایپ ها رو coerse کنه یا Box کنه یا به عبارتی دیگر سعی داره دوتا عبارت رو به یه تایپ تبدیل کنه
ایونت لوپ چیه؟
ایونت لوپ یه مکانیسمیه تو محیط اجرای جاوااسکریپت (مثل مرورگر یا Node.js) که کارش مدیریت عملیاتهای همزمان (Synchronous) و ناهمزمان (Asynchronous) هست. اینطوری کار میکنه:
-
عملیاتهای همزمان: وقتی کد جاوااسکریپت اجرا میشه، عملیاتهای عادی (مثل محاسبات ساده) مستقیم تو کال استک (Call Stack) اجرا میشن.
-
عملیاتهای ناهمزمان: اگر به یه عملیات ناهمزمان برخورد کنیم (مثل
setTimeout
یا یه درخواست HTTP)، این عملیات به Web API (تو مرورگر) یا Node.js API (تو سرور) سپرده میشه تا تو پسزمینه انجام بشه. -
صفحات انتظار: وقتی عملیات ناهمزمان تموم شد، تابع مربوط به اون (مثلاً یه تابع callback) تو یه صف قرار میگیره. دو نوع صف داریم:
-
صف میکروتسکها (Microtask Queue): این صف برای چیزایی مثل Promiseها (
then
,catch
,finally
) وqueueMicrotask
استفاده میشه. -
صف ماکروتسکها (Macrotask Queue): این صف برای چیزایی مثل
setTimeout
، درخواستهای HTTP و رویدادهای UI (مثل کلیک یا اسکرول) استفاده میشه.
-
-
نقش ایونت لوپ: ایونت لوپ مدام چک میکنه که آیا کال استک خالیه یا نه. اگر خالی بود، اول سراغ صف میکروتسکها میره و همهی کارهای اون صف رو انجام میده. بعدش سراغ صف ماکروتسکها میره و فقط یه کار از اون صف رو انجام میده. اما بعد از هر ماکروتسک، دوباره چک میکنه که آیا میکروتسک جدیدی اضافه شده یا نه. این روند مدام تکرار میشه.
ا event delegation چیه؟
اEvent Delegation یه تکنیک تو جاوااسکریپته که به جای اینکه به تکتک عناصر (مثلاً دکمهها یا لیستها) یه Event Listener وصل کنیم، فقط به پدرشون (Parent Element) یه Event Listener وصل میکنیم. وقتی یه ایونت (مثل کلیک) روی یه عنصر اتفاق میافته، این رویداد به سمت بالا تو DOM حرکت میکنه (به این میگن Event Bubbling) و به پدرش میرسه. اونجا، پدر میتونه تشخیص بده که رویداد روی کدوم عنصر اتفاق افتاده و براساس اون عمل کنه.
چرا Event Delegation مفیده؟
-
بهینهتر و سریعتر: به جای اینکه به صدها عنصر Event Listener وصل کنیم، فقط یه دونه وصل میکنیم. این کار حافظه کمتری مصرف میکنه و عملکرد برنامه رو بهتر میکنه، مخصوصاً برای لیستهای بزرگ یا عناصری که مدام تغییر میکنن.
-
کد تمیزتر و سادهتر: فقط یه بار کد رو مینویسی و همه چیز رو تو همون پدر مدیریت میکنی. اینطوری کدت مرتبتر و قابل نگهداریتر میشه.
-
پشتیبانی از عناصر داینامیک: اگه عناصر جدیدی به صفحه اضافه بشن یا حذف بشن، نیازی نیست دستی Event Listener بهشون وصل یا ازشون حذف کنی. چون پدرشون داره همهچی رو مدیریت میکنه.
مثال:
فرض کن یه لیست داینامیک داری و میخوای وقتی روی هر آیتم کلیک میشه، یه کاری انجام بشه:
<ul id="parent-list">
<li>آیتم ۱</li>
<li>آیتم ۲</li>
<li>آیتم ۳</li>
</ul>
به جای اینکه به هر <li>
یه Event Listener وصل کنی، فقط به <ul>
یه دونه وصل میکنی:
document.getElementById('parent-list').addEventListener('click', function(event) {
if (event.target.tagName === 'LI') {
console.log('کلیک روی:', event.target.textContent);
}
});
ا event bubbling چیه؟
ا event capturing چیه؟
What is the difference between a Map
object and a plain object in JavaScript?
Both Map
objects and plain objects in JavaScript can store key-value pairs, but they have several key differences:
Feature | Map | Plain object |
---|---|---|
Key type | Any data type | String (or Symbol) |
Key order | Maintained | Not guaranteed |
Size property | Yes (size ) | None |
Iteration | forEach , keys() , values() , entries() | for...in , Object.keys() , etc. |
Inheritance | No | Yes |
Performance | Generally better for larger datasets and frequent additions/deletions | Faster for small datasets and simple operations |
Serializable | No | Yes |
Map/weakmap set/weakset
Feature | Map | WeakMap | Set | WeakSet |
---|---|---|---|---|
Key Types | Any data type | Objects (weak references) | Any data type (unique) | Objects (weak references, unique) |
Garbage Collection | Keys and values are not garbage collected | Keys can be garbage collected if not referenced elsewhere | Elements are not garbage collected | Elements can be garbage collected if not referenced elsewhere |
Use Cases | General-purpose key-value storage | Caching, private DOM node data | Removing duplicates, membership checks | Object weak references, custom use cases |
What are server-sent events?
Server-sent events (SSE) is a standard that allows a web page to receive automatic updates from a server via an HTTP connection. Server-sent events are used with EventSource
instances that opens a connection with a server and allows client to receive events from the server. Connections created by server-sent events are persistent (similar to the WebSocket
s), however there are a few differences:
Property | WebSocket | EventSource |
---|---|---|
Direction | Bi-directional – both client and server can exchange messages | Unidirectional – only server sends data |
Data type | Binary and text data | Only text |
Protocol | WebSocket protocol (ws:// ) | Regular HTTP (http:// ) |
What are JavaScript object property flags and descriptors?
In JavaScript, property flags and descriptors manage the behavior and attributes of object properties.
Property flags
Property flags are used to specify the behavior of a property on an object. Here are the available flags:
writable
: Specifies whether the property can be written to. Defaults totrue
.enumerable
: Specifies whether the property is enumerable. Defaults totrue
.configurable
: Specifies whether the property can be deleted or its attributes changed. Default istrue
.
How does JavaScript garbage collection work?
[[Notes/Software/Javascript/Garbage Collection|Garbage Collection]]
What is the purpose of the new
keyword?
The new
keyword in JavaScript is used to create an instance of a user-defined object type or one of the built-in object types that has a constructor function. When you use new
, it does four things: it creates a new object, sets the prototype, binds this
to the new object, and returns the new object.
function Person(name) {
this.name = name;
}
const person1 = new Person('Alice');
console.log(person1.name); // Alice
Explain the concept of debouncing and throttling
Debouncing and throttling are techniques used to control the rate at which a function is executed. Debouncing ensures that a function is only called after a specified delay has passed since the last time it was invoked. Throttling ensures that a function is called at most once in a specified time interval.
Debouncing delays the execution of a function until a certain amount of time has passed since it was last called. This is useful for scenarios like search input fields where you want to wait until the user has stopped typing before making an API call.
function debounce(func, delay) {
let timeoutId;
return function (...args) {
clearTimeout(timeoutId);
timeoutId = setTimeout(() => func.apply(this, args), delay);
};
}
Throttling ensures that a function is called at most once in a specified time interval. This is useful for scenarios like window resizing or scrolling where you want to limit the number of times a function is called.
function throttle(func, limit) {
let inThrottle;
return function (...args) {
if (!inThrottle) {
func.apply(this, args);
inThrottle = true;
setTimeout(() => (inThrottle = false), limit);
}
};
}
What are some techniques for reducing reflows and repaints?
To reduce reflows and repaints, you can minimize DOM manipulations, batch DOM changes, use CSS classes for style changes, avoid complex CSS selectors, and use requestAnimationFrame
for animations. Additionally, consider using will-change
for elements that will change frequently and avoid layout thrashing by reading and writing to the DOM separately.
What are Web Workers and how can they be used to improve performance?
Web Workers are a way to run JavaScript in the background, separate from the main execution thread of a web application. This helps in performing heavy computations without blocking the user interface. You can create a Web Worker using the Worker
constructor and communicate with it using the postMessage
and onmessage
methods.
// main.js
const worker = new Worker('worker.js');
worker.postMessage('Hello, worker!');
worker.onmessage = function (event) {
console.log('Message from worker:', event.data);
};
// worker.js
onmessage = function (event) {
console.log('Message from main script:', event.data);
postMessage('Hello, main script!');
};
What is the Factory pattern and how is it used?
The Factory pattern is a design pattern used to create objects without specifying the exact class of the object that will be created. It provides a way to encapsulate the instantiation logic and can be particularly useful when the creation process is complex or when the type of object to be created is determined at runtime.
For example, in JavaScript, you can use a factory function to create different types of objects:
function createAnimal(type) {
if (type === 'dog') {
return { sound: 'woof' };
} else if (type === 'cat') {
return { sound: 'meow' };
}
}
const dog = createAnimal('dog');
const cat = createAnimal('cat');
خطای chunk load error
برای موقعیه که وقتی یه کامپوننت یه کامپپونت دیگه که لود میکنه نیست مخصوصا توی lazy loading میتونیم با susspene جلوی ترکیدن صفحه رو بگیریم
ا shadow dom چیه
اShadow DOM یه تکنولوژی در Web Platformه که بهت اجازه میده یه درخت DOM ایزوله داخل یه المنت بسازی.
یعنی یه جور «مینی DOM» داخل یه المنت که بقیهی صفحه نمیتونن راحت بهش دسترسی داشته باشن یا روش تاثیر بذارن (مگر با اجازهی تو).
📦 چه مشکلی رو حل میکنه؟
فرض کن یه کامپوننت my-button
ساختی که یه button
با استایل خاصه. حالا توی صفحه یکی دیگه هم یه استایل global تعریف کرده:
button { background: red; }
بدون shadow DOM، اون استایل قرمز کل دکمههای توی صفحه رو تغییر میده—even توی کامپوننتت!
ولی با shadow DOM:
-
استایلها و DOM داخلی ایزوله میشن
-
از بیرون نمیتونن تغییرش بدن
-
تو هم نمیتونی اتفاقی چیزی از بیرون خراب کنی
const shadow = this.attachShadow({ mode: 'open' }); shadow.innerHTML = ` <style> button { background: blue; color: white; border: none; padding: 10px; border-radius: 8px; } </style> <button>Click me</button> `; } } customElements.define('my-button', MyButton);
چجوری استیت رو به صورت سینک اپدیت کنیم؟
اReact توی نسخههای جدید (از 18 به بعد) آپدیتها رو batch میکنه (یعنی چند آپدیت رو با هم جمع میکنه) تا performance بهتر بشه.
اما گاهی وقتا لازمه یه آپدیت فوراً اجرا بشه، مثلاً:
-
میخوای بلافاصله بعد از یه تغییر در DOM اندازه بگیری
-
انیمیشن یا ترنزیشن خاصی داری
-
یه ورودی کاربر سریع نیاز به جواب داره
-
باید قبل از کاری که React هنوز نرفته سمتش، یه چیز رو توی DOM ببینی یا log کنی
import { flushSync } from 'react-dom';
flushSync(() => { setState(newValue); // فوراً اینو رندر کن });