جاوااسکریپت | JavaScript
506 subscribers
654 photos
139 videos
3 files
512 links
کانال @IR_javascript حاوی اطلاعات مفید در حوزه برنامه نویس فرانت که بصورت روزانه بروز می‌شود.
در این کانال شما به:
[1] مطالب تازه
[2] تحلیل‌های عمیق
[3] نکات آموزشی
[4] چالش
[5] ابزار و راهنمایی‌های کاربردی
دسترسی خواهید داشت.

🆔@IR_javascript
Download Telegram
ثبت رویدادهای عناصر DOM در کنسول

تابع monitorEvents برای هر رویدادی که روی یک گره DOM (مانند یک عنصر HTML) رخ می‌دهد، پیامی در کنسول ثبت می‌کند.

monitorEvents(document.body);


📋 رویدادهای گزارش‌شده روی `document.body`

همان‌طور که مشاهده می‌کنید، گزارش‌گیری از تمام رویدادها می‌تواند بسیار شلوغ و پرحجم باشد.
برای جلوگیری از این مسئله، می‌توانید فقط نوع رویدادهایی که برایتان اهمیت دارند را به‌صورت آرایه‌ای مشخص کنید:

monitorEvents(document.body, ["pointerenter", "click"]);


برای غیرفعال کردن این گزارش‌ها، از تابع unmonitorEvents استفاده کنید:

unmonitorEvents(document.body);




#️⃣#tool
👥@IR_javascript_group
🆔@IR_javascript
شناسایی شنونده‌های رویداد (Event Listeners) متصل‌شده

برای مشاهده‌ی تمامی شنونده‌های رویداد (Event Handlers) که به یک عنصر متصل شده‌اند، می‌توانید از تابع getEventListeners استفاده کنید:

getEventListeners(document.body);


با اجرای این دستور، می‌توانید موارد زیر را مشاهده کنید:

* نوع رویداد (مانند click`، `scroll و...)
* ویژگی‌هایی مانند اینکه آیا شنونده فقط یک‌بار اجرا می‌شود (once) یا خیر
* و همچنین ارجاع مستقیم به تابعی که به‌عنوان handler تعریف شده است

برای مشاهده‌ی کد منبع تابع، کافی‌ست روی آن راست‌کلیک کرده و گزینه‌ی Show function definition را انتخاب کنید تا مستقیماً به محل تعریف تابع هدایت شوید.


#️⃣#tool
👥@IR_javascript_group
🆔@IR_javascript
👍1
یافتن اشیاء براساس سازنده (Constructor)
تابع queryObjects فهرستی از اشیایی را بازمی‌گرداند که با استفاده از سازنده‌ای که به آن پاس داده‌اید، ایجاد شده‌اند.

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


queryObjects(Function);



#️⃣#tool
👥@IR_javascript_group
🆔@IR_javascript
جمع‌آوری ضبط عملکرد

ابزار Performance Profiler در Chrome DevTools ابزاری قدرتمند برای ثبت دقیق جزئیات عواملی است که بر سرعت بارگذاری صفحه شما تأثیر می‌گذارند.

شما می‌توانید در بخش Performance پنل DevTools یک پروفایل را آغاز کرده و پس از اتمام، ضبط را متوقف کنید. با این حال، این روش می‌تواند با چند مشکل همراه باشد:

کنترل دقیقی بر زمان جمع‌آوری داده‌ها ندارید و ناچارید بعداً روی بخش مورد نظر بزرگ‌نمایی کنید.

ضبط چندین پروفایل تکراری فرآیندی کند و دستی است.

بارگذاری ردگیری‌های بزرگ (Large traces) در ابزار توسعه‌دهنده زمان‌بر است.

توابع profile و profileEnd تمام این مشکلات را برطرف می‌کنند. با استفاده از این توابع، می‌توانید به‌صورت برنامه‌ریزی‌شده و دقیقاً در زمان مناسب، ضبط عملکرد را آغاز و پایان دهید:
console.profile();
// اجرای مجموعه‌ای از عملیات کند
console.profileEnd();



#️⃣#tool
👥@IR_javascript_group
🆔@IR_javascript
👍1
عبارات زنده (Live Expressions)
اگر مرتباً یک عبارت جاوااسکریپت خاص را برای بررسی وضعیت صفحه اجرا می‌کنید، «عبارات زنده» گزینه‌ای ایده‌آل هستند. به جای اجرای دستی کد، با استفاده از این قابلیت می‌توانید Chrome را طوری پیکربندی کنید که به‌طور خودکار و پیوسته همان عبارت را اجرا کند.


#️⃣#tool
👥@IR_javascript_group
🆔@IR_javascript
👍2
تنظیمات کنسول
برای پیکربندی تنظیمات کنسول، روی آیکون چرخ‌دنده در گوشه بالای سمت راست زبانه Console کلیک کنید.

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

علاوه بر این، می‌توانید نوع پیام‌های تولیدشده توسط Chrome را فعال یا غیرفعال کنید:

Hide network: پنهان‌کردن درخواست‌های ناموفق

Log XMLHttpRequests: ثبت همه درخواست‌های Ajax یا Fetch در صفحه

Show CORS errors in console: نمایش علت شکست درخواست‌های بین‌مبدأ (Cross-Origin)

با این تنظیمات، خروجی کنسول می‌تواند شامل گزارش درخواست‌ها و همچنین خطاهای CORS باشد.

#️⃣#tool
👥@IR_javascript_group
🆔@IR_javascript
👍1
This media is not supported in your browser
VIEW IN TELEGRAM
🖤شهادت رسول اکرم صلی الله علیه و آله و امام مجتبی علیه السلام.

🔗https://www.aparat.com/v/c50akua
#️⃣#event
👥@IR_javascript_group
🆔@IR_javascript
10👎7
استفاده از await در سطح بالای ماژول‌های ES

نوشتن کدهای ناهمگام (asynchronous) در جاوااسکریپت تا چندی پیش یک محدودیت مهم داشت: کلیدواژه‌ی await تنها درون یک تابع async قابل استفاده بود. این موضوع با معرفی ویژگی Top-Level Await در استاندارد ES2022 تغییر کرد؛ قابلیتی مدرن در ماژول‌های ES که امکان اجرای الگوهای جدیدی از کد ناهمگام را در سطح ماژول فراهم می‌کند.

‏Top-Level Await چیست؟

به‌طور سنتی، دستور await تنها درون توابع async معتبر بود:


//  خطای نحوی (SyntaxError) در خارج از تابع async
const result = await fetchData();


اکنون با استفاده از Top-Level Await، می‌توانید آن را در سطح بالای ماژول ES اجرا کنید:
//  این کد در یک ماژول ES قابل اجرا است
const result = await fetchData();


در گذشته برای استفاده از await در سطح بالا، ناچار بودید آن را درون یک تابع ناهمگام خوداجرا (IIFE) بپیچید:
(async () => {
const result = await fetchData();
})();


با Top-Level Await می‌توانید با چنین کدهای زائد خداحافظی کنید و منطق ناهمگام خود را به‌صورت مستقیم در بالاترین سطح ماژول بنویسید؛ کدی ساده‌تر، خواناتر و تمیزتر.

⚠️ نکته مهم

‏Top-Level Await فقط در ماژول‌های جاوااسکریپت پشتیبانی می‌شود، نه در CommonJS (یعنی require) و نه در تگ‌های <script> سنتی که فاقد ویژگی type="module" هستند (زیرا این حالت در «مد کلاسیک» اجرا می‌شود). همچنین، فایل‌های با پسوند .cjs در Node.js از آن پشتیبانی نمی‌کنند.


#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
شکستن کلمات همراه با خط تیره 😉

موضوع ساده به نظر می‌رسد — وقتی یک کلمه طولانی در یک خط جا نمی‌شود، باید آن را با خط تیره به خط بعد منتقل کرد. اما چطور این کار را به‌درستی انجام دهیم تا هم ظاهر متن زیبا باشد و هم ساختار آن به‌هم نریزد؟

بیایید بررسی کنیم برای این کار در CSS چه نیاز داریم. ☺️

برای شکستن صحیح کلمات همراه با خط تیره، سه ویژگی اصلی مورد نیاز است:

✔️ overflow-wrap: break-word; — این ویژگی باعث می‌شود کلمات طولانی (مثل نشانی‌های اینترنتی یا اصطلاحات پیچیده) در صورت کمبود فضا به خط بعد منتقل شوند.

✔️ word-break: break-word; — این ویژگی اجازه می‌دهد کلمات در نقاط مناسب نیز شکسته شوند، اگر در یک خط جا نشوند.

✔️ hyphens: auto; — مسئول اضافه کردن خودکار خط تیره هنگام شکستن کلمات است، بر اساس قواعد زبان مورد استفاده.

نمونه کد:

.text {
overflow-wrap: break-word; /* اجازه شکستن کلمات طولانی */
word-break: break-word; /* شکستن کلمات در نقاط مناسب */
hyphens: auto; /* افزودن خودکار خط تیره هنگام شکستن */
}


حالا همه‌چیز طبق قواعد زبان کار خواهد کرد: کلمات همراه با خط تیره شکسته می‌شوند و در عین حال متن، منظم و زیبا باقی می‌ماند. 👍


#️⃣#tip #css
👥@IR_javascript_group
🆔@IR_javascript
Atropos.js

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

🔗https://atroposjs.com/
#️⃣#npm_module
👥@IR_javascript_group
🆔@IR_javascript
👍1
خب، نتایج بنچمارک عملکرد منتشر شد ( [لینک](https://krausest.github.io/js-framework-benchmark/2025/table_chrome_139.0.7258.67.html) )؛ این بار روی آخرین نسخه کروم و همراه با پچ‌های جدیدی که در نسخه آلفای Vue 3.6 ارائه شده‌اند.

به‌دلیل حجم بالاتر باندل و لزوم پشتیبانی از APIهای قدیمی، اندازه‌ی فریم هنوز کمی بزرگ‌تر از Svelte و Solid است، اما در سایر شاخص‌ها کاملاً در سطح رقبا و حتی در برخی موارد بهتر عمل می‌کند.


#️⃣#tool
👥@IR_javascript_group
🆔@IR_javascript
یادآوری درباره‌ی ‎`.setProperty()` و متغیرهای CSS 😉

همه‌ی ما متد ‎`.setProperty()` می‌شناسیم و معمولاً زمانی به یادش می‌افتیم که لازم باشد یک ویژگی CSS را مستقیماً از طریق JavaScript تغییر دهیم.
اما به‌راحتی می‌توان فراموش کرد که با همین متد می‌توان متغیرهای CSS را نیز تغییر داد — و این در بسیاری موارد بسیار کارآمدتر است.

برای نمونه، یک متغیر سراسری در ‎`:root`‎:

:root {
--main-color: #333;
}


و در JavaScript:

// تغییر خود متغیر، نه ویژگی مستقیم
document.documentElement.style.setProperty('--main-color', '#ff6600');


اکنون تمام عناصری که مقدار color: var(--main-color) دارند، به‌طور خودکار مقدار جدید را دریافت می‌کنند. 👍

کجا استفاده از متغیرها از طریق ‎`.setProperty()`‎ بیش‌تر به چشم می‌آید؟

✔️ انیمیشن‌ها — تنها با تغییر یک متغیر، تمام استایل‌های مرتبط به‌صورت روان و از طریق CSS transition به‌روز می‌شوند.
✔️ استفاده در content — می‌توان متن یا نمادی را در یک متغیر ذخیره کرد و آن را به‌صورت پویا تغییر داد.

.btn::after {
content: var(--btn-label);
}


btn.style.setProperty('--btn-label', '"✓"');


در نتیجه، ‎`.setProperty()`‎ تنها برای تغییر ویژگی‌ها نیست، بلکه ابزاری قدرتمند برای مدیریت متغیرهای CSS نیز به‌شمار می‌رود ⚡️

#️⃣#tip #css
👥@IR_javascript_group
🆔@IR_javascript
👍1
من همیشه فکر می‌کردم توسعه‌ی فرانت‌اند به‌مراتب دشوارتر از بک‌اند است، اما توضیح این موضوع برای سایر توسعه‌دهندگان همیشه سخت بود. امروز خواستم نظر یک مدل زبانی (که به‌نوعی نماینده‌ی «نظر کلی کارشناسان» است) را بررسی کنم.

نتیجه جالب بود:
توسعه‌ی فرانت‌اند برای انسان‌ها سخت‌تر است، زیرا بک‌اند بیشتر ماهیتی ریاضی و مبتنی بر قواعد دارد و درک آن چندان دشوار نیست؛ همه‌چیز با فرمول‌ها و الگوهای قابل پیش‌بینی پیش می‌رود.

اما فرانت‌اند؟ اینجا قیاس بی‌نظیری مطرح شد: زیست‌شناسی!

🔹 مقیاس‌پذیری بک‌اند: شبیه ریاضیات؛ با افزودن نودهای بیشتر، شارد کردن پایگاه داده یا بهینه‌سازی کوئری‌ها، سیستم طبق فرمول‌ها و قوانین قابل‌پیش‌بینی رشد می‌کند.

🔹 تغییرات فرانت‌اند: شبیه زیست‌شناسی؛ جهش‌های کوچک (مثل دستگاه جدید، ویژگی تازه‌ی مرورگر یا نیاز متفاوت در تجربه‌ی کاربری) رفتاری نوظهور، اغلب آشفته و موردی ایجاد می‌کنند که باید تک‌به‌تک با آن‌ها سازگار شد.

زیست‌شناسی بسیار پیچیده‌تر از ریاضیات است — زیرا ریاضیات قانون‌مند و قطعی است، اما زیست‌شناسی پدیده‌ای نوظهور، پر از استثنا، وابسته به زمینه و همواره در حال تغییر.

به همین دلیل است که فرانت‌اند (شبیه زیست‌شناسی) برای انسان‌ها به‌مراتب شلوغ‌تر و دشوارتر به نظر می‌رسد، حتی اگر بک‌اند (شبیه ریاضیات) از نظر انتزاعی ژرف‌تر باشد.

#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
🤔1
اوایل همین ماه، شرکت ByteDance — خالق TikTok و CapCut — از Lynx.js رونمایی کرد. این خبر می‌تواند برای جامعه‌ی Vue بسیار مهم باشد، چراکه احتمالاً امکان توسعه‌ی اپلیکیشن‌های بومی با Vue را فراهم خواهد کرد!

یک فریم‌ورک رابط کاربری مبتنی بر جاوااسکریپت است که به توسعه‌دهندگان اجازه می‌دهد اپلیکیشن‌های وب و موبایل را به‌گونه‌ای بسازند که احساس بومی (Native) داشته باشند؛ به این ترتیب رویای قدیمی فرانت‌اندکاران و توسعه‌دهندگان UI یعنی «یک بار بنویس، همه‌جا اجرا کن» را محقق می‌کند.
با این حال، ترکیب Vue و Lynx یک فرصت هیجان‌انگیز است:

اپلیکیشن‌های واقعاً بومی

با استفاده از همان دانش وب

و منحنی یادگیری ساده‌ی Vue

با رشد این اکوسیستم، انتظار می‌رود ابزارها، کامپوننت‌ها و الگوهای بهتری شکل بگیرند و Vue Lynx به گزینه‌ای جدی برای توسعه‌ی کراس‌پلتفرم تبدیل شود.
#️⃣#tool
👥@IR_javascript_group
🆔@IR_javascript
استفاده از `distinctUntilChanged` و `debounceTime`: بهینه‌سازی جستجو 👩‍💻

وقتی فرم ایجاد می‌کنیم، مهم است که از ارسال درخواست‌های غیرضروری به سرور جلوگیری کنیم. دو اپراتور RxJS به نام‌های `debounceTime` و `distinctUntilChanged` در این زمینه به ما کمک می‌کنند:

* ✔️ debounceTime اجرای عملیات را با تأخیر انجام می‌دهد.
* ✔️ distinctUntilChanged مقادیر تکراری را نادیده می‌گیرد.

### مثال:

this.searchForm.controls.searchField.valueChanges
.pipe(
debounceTime(300), // صبر می‌کنیم ۳۰۰ میلی‌ثانیه بعد از آخرین ورودی
distinctUntilChanged() // مقادیر تکراری را نادیده می‌گیریم
)
.subscribe(searchTerm => {
console.log('درخواست به سرور:', searchTerm);
this.searchData(searchTerm); // ارسال درخواست
});


### عملکرد هر اپراتور:

⭐️ debounceTime(300) — ارسال درخواست را ۳۰۰ میلی‌ثانیه بعد از آخرین ورودی به تأخیر می‌اندازد. این کار باعث می‌شود برای هر کاراکتر یک درخواست ارسال نشود، که مخصوصاً هنگام تایپ سریع بسیار مفید است.

⭐️ distinctUntilChanged() — تضمین می‌کند که درخواست تنها وقتی مقدار تغییر کند ارسال شود. اگر کاربر همان عبارت جستجو را دوباره وارد کند، درخواست تکراری ارسال نخواهد شد.

---

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


#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
نحوه تنظیم Autocomplete با گزینه‌های محدود، ولی با امکان وارد کردن مقادیر دلخواه در TypeScript

اخیراً با یک چالش جالب مواجه شدم: می‌خواستم یک نوع (Type) بسازم که هم بتواند هر رشته‌ای را بپذیرد، و هم برای چند مقدار از پیش تعریف‌شده رفتاری خاص داشته باشد.

معمولاً این کار با enum یا اشیاء حل می‌شد، اما یک روش شیک‌تر هم وجود دارد!

### راهکار: استفاده از string & {} در انتهای Union

این تکنیک اجازه می‌دهد نوعی تعریف کنیم که انعطاف‌پذیر باشد و همزمان در Autocomplete گزینه‌های مشخص را پیشنهاد دهد.

#### مثال:

type MyType = 'Option1' | 'Option2' | string & {};


### توضیح:

* MyType می‌تواند هر رشته‌ای را بپذیرد.
* با این حال، Autocomplete تنها 'Option1' و 'Option2' را پیشنهاد می‌دهد.
* دلیلش این است که ترکیب string & {} امکان استفاده از رشته‌ها را حفظ می‌کند ولی پیشنهادها محدود به مقادیر مشخص شده در Union می‌ماند.

---

نتیجه: این روش برای مواقعی مناسب است که می‌خواهید انعطاف نوع را حفظ کنید و همزمان به راحتی بتوانید گزینه‌های از پیش تعریف‌شده را در Autocomplete نمایش دهید. 👍


#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
اختصارات منطقی در انتساب‌ها در JavaScript 🤔

ECMAScript ۲۰۲۱ سه اپراتور مفید را اضافه کرده است:

✔️ انتساب x ||= y — اگر x مقدار «فالس» داشته باشد → `x = y`؛
✔️ انتساب x ??= y — اگر x مقدار null یا undefined داشته باشد → x = y (صفر، رشته خالی و false حفظ می‌شوند)؛
✔️ انتساب x &&= y — اگر x مقدار «ترو» داشته باشد → x = y.

‼️ نکته مهم: چرا x ||= y و x = x || y همیشه معادل هم نیستند

به طور خلاصه: اپراتورهای اختصاری مقدار سمت چپ انتساب (LHS) را فقط یک بار محاسبه می‌کنند، در حالی که حالت x = x || y ممکن است LHS را دو بار محاسبه کند. این مسئله زمانی مشکل‌ساز می‌شود که LHS فقط یک متغیر ساده نباشد، بلکه یک عبارت شامل فراخوانی‌ها، getterها یا کلیدهای محاسبه‌شده باشد.

👩‍💻 مثال کمینه و قابل بازتولید:

let i = 0;
function getKey() { console.log('getKey'); return 'k' + (++i); }

const a = {};
a[getKey()] ||= 1; // getKey یک بار فراخوانی می‌شود — ایمن

i = 0;
const b = {};
b[getKey()] = b[getKey()] || 1; // getKey دو بار فراخوانی می‌شود — اثر جانبی!


➡️ در عبارت b[...] = b[...] || 1`، `getKey() ممکن است در فراخوانی‌های مختلف کلیدهای متفاوت تولید کند یا اثرات جانبی دیگری داشته باشد — در نتیجه منطق برنامه خراب می‌شود. اما ||= چنین خطری ندارد، چون ارجاع به b[getKey()] فقط یک بار گرفته می‌شود.

نتیجه:
اپراتورهای ||=, ??= و &&= تنها «شیرینی سینتکسی» نیستند؛ بلکه روشی برای جلوگیری از باگ‌های پنهان هستند، به خصوص زمانی که LHS شامل عبارات با اثر جانبی است.

پیشنهاد استفاده:
⏺️ ??= برای مقداردهی پیش‌فرض واقعی،
⏺️ ||= برای زمانی که هر مقدار فالس مدنظر است،
⏺️ &&= برای به‌روزرسانی شرطی. 👍




#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
آشنایی با ویژگی rel در تگ <link> و تأثیر مقادیر آن بر رندر صفحه 🤨

تگ <link> برای اتصال منابع خارجی به سند HTML استفاده می‌شود.

ویژگی کلیدی این تگ، rel است که نوع ارتباط با منبع را مشخص می‌کند: این منابع می‌توانند شامل استایل‌ها، فونت‌ها، آیکون‌ها، مانیفست‌ها و موارد دیگر باشند. نحوه پردازش این منابع توسط مرورگر کاملاً وابسته به مقدار این ویژگی است و همین موضوع به طور مستقیم بر رندر صفحه، سرعت بارگذاری و دسترسی‌پذیری آن تأثیر می‌گذارد. 👨‍🏫

در تصاویر بالا، من به تفصیل مقادیر اصلی ویژگی rel و تأثیر آن‌ها بر عملکرد صفحه را بررسی کرده‌ام. ⬆️

توصیه‌های کاربردی:
✔️ فونت و CSS ‌های حیاتی را فوراً بارگذاری کنید (با stylesheet یا preload)؛
✔️ برای منابع از دامنه‌های دیگر از preconnect یا dns-prefetch استفاده کنید؛
✔️ منابع کم‌اهمیت‌تر را می‌توان به صورت غیرهمزمان بارگذاری کرد (prefetch).

نتیجه‌گیری:
استفاده از این تکنیک‌ها به کاهش تاخیرها، کاهش اثر «پرش صفحه» (FOUC) و بهبود تجربه کاربری کمک می‌کند، به‌ویژه در دستگاه‌های موبایل.

#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript