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

🆔@IR_javascript
Download Telegram
ویدیو دوبله شده در مورد الگو های طراحی در اپلیکیشن های تحت وب [+لینک]
در این دوره، با الگوهای طراحی برای پروژه‌های فرانت‌اند با استفاده از جاوا اسکریپت آشنا خواهید شد. مزایا و چالش‌های الگوهای طراحی را درک خواهید کرد و نحوه پیاده‌سازی الگوهای مختلف برای ارتقای خوانایی، قابلیت استفاده مجدد، مدولار بودن و مقیاس‌پذیری پروژه‌های جاوا اسکریپت ساده خود را خواهید آموخت.

🔗https://www.aparat.com/v/phnxki9?playlist=20513366
#️⃣#tip #dub
👥@IR_javascript_group
🆔@IR_javascript
👍1
سیگنال: جادوی واکنش‌گرایی در برنامه‌نویسی

باور دارم که درک چگونگی کارکرد یک پدیده، لذت بیشتری به زندگی شما می‌بخشد؛ زیرا باعث می‌شود در آنچه انجام می‌دهید توانمندتر باشید.
بسیاری از چارچوب‌های دیگر همچون Angular، Solid، Vue و Qwik نیز چنین رویکردی دارند. حتی پیشنهادی برای افزودن سیگنال‌ها به خود زبان جاوااسکریپت هم ارائه شده است.

🔹 اجزای اصلی سیگنال
۱. مقدار (value): همان داده‌ای که نگه‌داری می‌شود.
۲. مشترکان (subscribers): توابعی که باید در صورت تغییر مقدار اجرا شوند.
۳. اثرها (effects): توابعی که به تغییر سیگنال واکنش نشان می‌دهند.

سیگنال در اصل ظرفی است که یک مقدار و مجموعه‌ای از مشترکان را نگه می‌دارد و هنگام تغییر مقدار، آن‌ها را آگاه می‌سازد. بنابراین، سیگنال به‌تنهایی کاری انجام نمی‌دهد:
function state(value) {
const signal = { value, subscribers: new Set() }
return signal
}


برای واکنش به تغییرات سیگنال، به «اثرها» نیاز داریم. اثرها همان توابعی هستند که هنگام تغییر سیگنال اجرا می‌شوند.

let activeEffect = null

function effect(fn) {
// تنظیم اثر فعال
activeEffect = fn
// اجرای اثر
fn()
}


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

let activeEffect = fn

function get(signal) {
// افزودن اثر به مشترکان
signal.subscribers.add(activeEffect)
// بازگرداندن مقدار
return signal.value
}


سپس، هنگامی که مقداری در سیگنال نوشته می‌شود، مشترکان آگاه می‌شوند

function set(signal, value) {
// به‌روزرسانی مقدار
signal.value = value
// آگاه‌سازی مشترکان
signal.subscribers.forEach(effect => effect())
}


از این پس تنها کافی است حالت (state) را به‌روزرسانی کنید؛ رابط کاربری در هر نقطه‌ای که از آن استفاده شده باشد تغییر خواهد کرد. اگر با الگوی «ناظر» (observer) آشنا باشید، سیگنال‌ها نوعی نسخه‌ی پیشرفته‌تر از observable هستند و چارچوب‌هایی مانند Svelte کارهای پیچیده‌ی بسیاری در پشت صحنه انجام می‌دهند تا عملکرد آن‌ها بهینه باشد.

به‌عنوان نمونه، یک شمارنده با پیاده‌سازی ساده‌ی سیگنال‌ها در یک فایل HTML معمولی:

<script type="module">
import { state, set, get, effect } from './signals.js'

// ایجاد سیگنال
const count = state(0)

// اتصال به عناصر DOM
const btn = document.querySelector('button')
btn.onclick = () => set(count, get(count) + 1)

// ایجاد اثر برای قالب
effect(() => btn.textContent = get(count))
</script>

<button>0</button>



#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
👎1
شما اچ‌تی‌ام‌ال را نمی‌شناسید: انواع اسکریپت‌ها

برای افزودن اسکریپت‌ها به صفحه از عنصر <script> استفاده می‌شود. اسکریپت‌ها انواع مختلفی دارند که بر رفتار و شیوه‌ی بارگذاری آن‌ها تأثیر می‌گذارد.

## 🔹 اسکریپت کلاسیک

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

<script>
console.log("Hello from classic script!");
</script>


---

## 🔹 اسکریپت داده (type="not-javascript")

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

<script type="not-javascript">
{
"user": "Ali",
"role": "admin"
}
</script>


---

## 🔹 اسکریپت خارجی کلاسیک

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

<script src="/script.js"></script>


📄 در فایل script.js می‌نویسیم:

console.log("Loaded from external file!");


---

## 🔹 اسکریپت خارجی با async

وقتی async بذاریم، فایل هم‌زمان با پردازش صفحه بارگذاری میشه. ولی به محض اینکه کامل دانلود بشه، اجرا میشه و پردازش صفحه رو همون لحظه متوقف می‌کنه.

<script src="/script.js" async></script>


---

## 🔹 اسکریپت خارجی با defer

اینجا فایل بارگذاری میشه، اما اجرای اون تا وقتی کل DOM آماده نشه عقب میفته. به همین خاطر همیشه مطمئنی به ترتیب ظاهر شدنش در HTML اجرا میشه.

<script src="/script.js" defer></script>


---

## 🔹 اسکریپت با async defer

اگه هر دو ویژگی رو با هم بذاریم، در عمل مثل async رفتار می‌کنه و defer نادیده گرفته میشه.

<script src="/script.js" async defer></script>


---

## 🔹 اسکریپت ماژول (type="module")

اینجا میشه از import و export استفاده کرد. ماژول‌ها مثل defer هستن: در زمان بارگذاری پارسر رو متوقف نمی‌کنن و بعد از آماده شدن DOM اجرا می‌شن.

<script type="module">
import { sayHello } from "./utils.js";
sayHello("Ali");
</script>


📄 در فایل utils.js:

export function sayHello(name) {
console.log("Hello, " + name);
}


---

## 🔹 ماژول با async

همه‌ی وابستگی‌های ماژول به صورت موازی بارگذاری میشن. وقتی آخرینش آماده شد، ماژول اجرا میشه.

<script type="module" src="/main.js" async></script>


---

## 🔹 اسکریپت با nomodule

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

<script src="/fallback.js" nomodule></script>


---

## 🔹 نقشه‌ی واردات (type="importmap")

به مرورگر می‌گه چطور اسم‌های مستعار ماژول‌ها رو به مسیر واقعی فایل‌ها وصل کنه.

<script type="importmap">
{
"imports": {
"lib": "/js/library-v1.js"
}
}
</script>

<script type="module">
import { doSomething } from "lib";
doSomething();
</script>


---

## 🔹 قوانین بارگذاری پیش‌دستانه (type="speculationrules")

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

<script type="speculationrules">
{
"prefetch": [
{ "source": "document", "urls": ["/next-page.html"] }
]
}
</script>





#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
👍2
## تفاوت بین Number.isFinite و isFinite چیست؟ 🤨

در JavaScript دو تابع برای بررسی این که آیا یک مقدار یک عدد محدود (Finite) است یا نه وجود دارد: Number.isFinite و تابع سراسری isFinite. بیایید با هم تفاوت آن‌ها را بررسی کنیم!

---

### ✔️ Number.isFinite

این تابع بررسی می‌کند که آیا مقدار داده‌شده یک عدد محدود واقعی است یا خیر.

تفاوت اصلی: این تابع تبدیل نوع داده‌ای انجام نمی‌دهد.

console.log(Number.isFinite(10));        // true
console.log(Number.isFinite('10')); // false
console.log(Number.isFinite(Infinity)); // false


---

### ✔️ isFinite

این تابع بررسی می‌کند که آیا مقدار داده‌شده قابل تبدیل به عدد است و پس از تبدیل، یک عدد محدود می‌باشد یا خیر.

console.log(isFinite(10));        // true
console.log(isFinite('10')); // true، رشته به عدد تبدیل می‌شود
console.log(isFinite('abc')); // false
console.log(isFinite(true)); // true، true به 1 تبدیل می‌شود


---

### 🔹 جمع‌بندی

* 🧩 Number.isFinite: وقتی نیاز به بررسی دقیق و بدون تبدیل نوع عدد محدود دارید.
* 🧩 isFinite: وقتی می‌خواهید بررسی کنید که مقدار قابل تبدیل به عدد محدود است یا نه. 👍



#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
👍1
بررسی آزاردهنده‌ترین عنصر در میان تمام ویجت‌های استاندارد HTML

#️⃣#tip #css
👥@IR_javascript_group
🆔@IR_javascript
👍3
LeaderLine

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

🔗https://anseki.github.io/leader-line/
#️⃣#npm_module
👥@IR_javascript_group
🆔@IR_javascript
👍1
حملات زنجیرهٔ تأمین (Supply Chain Attacks) نوعی حملهٔ سایبری است که به جای حملهٔ مستقیم به خود محصول یا سرویس هدف، به یکی از تأمین‌کننده‌ها، ابزارها یا وابستگی‌هایی که محصول استفاده می‌کند نفوذ می‌کند.

مثال ساده:

* فرض کن برنامه‌ای داری که از یک بسته‌ی جاوااسکریپت در npm استفاده می‌کند.
* یک هکر موفق می‌شود همان بسته یا نسخهٔ جدیدش را آلوده کند و کد مخرب داخل آن قرار دهد.
* وقتی نسخهٔ جدید بسته را نصب می‌کنید، کد مخرب به برنامهٔ شما نیز منتقل می‌شود.

بنابراین حملهٔ زنجیره‌ای یعنی حمله نه به خود برنامهٔ شما، بلکه به یک قطعه یا منبعی که برنامهٔ شما به آن وابسته است.

---

### npm-check-updates

این ابزار به شما امکان می‌دهد تا به جای استفاده از نسخه‌های مشخص‌شده در `package.json`، بسته‌ها را به آخرین نسخه‌های موجود ارتقا دهید.
شامل یک حالت تعاملی (-i) است که می‌توانید به‌صورت مرحله‌به‌مرحله ارتقاها را بررسی کرده و هرکدام را جداگانه انتخاب کنید.

نسخهٔ ۱۸.۲ ویژگی جدیدی به نام ‘cooldown’ اضافه کرده است که برای محافظت در برابر حملات زنجیرهٔ تأمین کاربرد دارد. این ویژگی تضمین می‌کند که نسخه‌های بسته حداقل به تعداد روز مشخصی قبل از ارتقا منتشر شده باشند، تا از استفادهٔ ناخواسته از نسخه‌های تازه و بالقوه آسیب‌پذیر جلوگیری شود.


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

به همین دلیل من عاشق کانستراکتورها (Constructors) هستم. اما منظور ما از کانستراکتور اینجا، ساخت طرح‌بندی‌ها و Layoutها است، نه ابزارهایی مثل Tilda.

امروز یک ابزار جدید پیدا کردم: FlexBox Labs

🔗https://flexboxlabs.netlify.app
#️⃣#tool
👥@IR_javascript_group
🆔@IR_javascript
👍4🔥1
اگر زمانی که موتور خودرو را روشن می‌کنیم، موتور سرد باشد، Cold Start رخ می‌دهد. در این حالت، دور موتور بیش از حد نرمال افزایش می‌یابد تا زمانی که موتور به دمای محیطی که در آن قرار دارد برسد. این کار باعث می‌شود موتور سریع‌تر به شرایط عملکردی مناسب خود برسد.

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

در سرویس‌های ابری (Cloud Services):
وقتی یک تابع یا کانتینر برای اولین بار اجرا می‌شود، سیستم باید محیط آن را آماده کند، کتابخانه‌ها و وابستگی‌ها را بارگذاری کند و سپس کد را اجرا کند. این زمان اولیه همان Cold Start است.


#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
1
### مقادیر دوگانه در ویژگی display در CSS 🤔

ویژگی display در CSS تعیین می‌کند که عناصر چگونه در صفحه نمایش داده شوند. هنگامی که از مقادیر دوگانه استفاده می‌کنیم، می‌توانیم دو نوع رفتار نمایش را برای یک عنصر ترکیب کنیم و در نتیجه انعطاف‌پذیری بیشتری به دست آوریم.

#### مقادیر دوگانه چیست؟

🧩 مقدار نخست، رفتار اصلی عنصر را مشخص می‌کند (مانند *block*، *inline* یا *flex*).
🧩 مقدار دوم، این رفتار را تکمیل و اصلاح می‌کند.

به‌عنوان نمونه، در حالت inline-block**، عنصر مانند یک عنصر درون‌خطی رفتار می‌کند، اما در عین حال می‌توان برای آن ابعاد مشخص کرد، درست مانند یک عنصر بلوکی. 👍

```html
<div style="display: inline-block; width: 100px; height: 50px; background-color: lightblue;">بلوک</div>
```

#### نمونه‌های دیگر:

✔️ **inline-block
:
⏺️ *inline* — عنصر در همان خط باقی می‌ماند.
⏺️ *block* — امکان تعریف اندازه‌ها فراهم است.

✔️ inline-flex:
⏺️ *inline* — ظرف (container) موجب شکستن خط نمی‌شود.
⏺️ *flex* — عناصر درون ظرف بر اساس قوانین فِلِکس‌باکس چیده می‌شوند.

---

### نتیجه‌گیری

مقادیر دوگانه در CSS باعث ساده‌تر شدن ساختار صفحه می‌شوند و امکان طراحی صفحات منعطف‌تر و واکنش‌گرا را با حداقل میزان کدنویسی فراهم می‌آورند. 💗



#️⃣#tip #css
👥@IR_javascript_group
🆔@IR_javascript
👍1
بستهٔ @unpic/vue قابلیت‌های قدرتمند و مدرن بهینه‌سازی تصویر را با حداقل پیکربندی به برنامه‌های Vue شما می‌آورد. با پشتیبانی درونی از بارگذاری تنبل، واکنش‌گرایی و انتخاب خودکار فرمت، هم در زمان توسعه صرفه‌جویی می‌شود و هم کارایی کلی به‌طور چشمگیری بهبود پیدا می‌کند.

+پشتیبانی از تصاویر واکنش‌گرا با استفاده از srcset
+بارگذاری تنبل به‌صورت پیش‌فرض
+انتخاب خودکار فرمت (برای نمونه WebP یا AVIF)
+سازگاری با سرویس‌هایی مانند Cloudinary، Imgix، Vercel، Sanity و بسیاری دیگر

🔗https://unpic.pics/
#️⃣#npm_module
👥@IR_javascript_group
🆔@IR_javascript
🔥2
### ویژگی decoding در تگ <img> واقعاً چه کاری انجام می‌دهد؟

(منبع: [TuneTheWeb](https://www.tunetheweb.com/blog/what-does-the-image-decoding-attribute-actually-do/))

این موضوع کمی پیچیده است و در مقاله اصلی حتی سخت‌تر توضیح داده شده، اما این دانش روزی به‌کار شما خواهد آمد.

احتمالاً دیده‌اید که بعضی تصاویر با ویژگی decoding="async" اضافه می‌شوند. شاید خودتان هم طبق توصیه‌های مقالات بهینه‌سازی عملکرد چنین ویژگی‌ای را استفاده کرده‌اید. اگر از کامپوننت Image در NextJS استفاده می‌کنید، به‌صورت پیش‌فرض این ویژگی روی تصاویر فعال است. اما آیا واقعاً مهم است؟

بارری پولارد این سوال را مطرح کرد و با صحبت با توسعه‌دهندگان مرورگرها به نکات جالبی رسید.

---

### مقادیر ویژگی decoding

طبق مشخصات، این ویژگی سه مقدار دارد:

* sync → درخواست رمزگشایی همزمان تصویر
* async → درخواست رمزگشایی ناهمزمان تصویر
* auto → مرورگر خودش تصمیم می‌گیرد

---

### روند کار تصویر در مرورگر

تصاویر مراحل زیر را طی می‌کنند:

1. مرورگر <img src="..."> را می‌بیند و ابتدا تصویر را از شبکه یا کش دریافت می‌کند.
2. سپس یک فرآیند کمکی تصویر را رمزگشایی می‌کند (تبدیل بایت‌ها به داده‌های قابل رندر).
3. در نهایت تصویر در صفحه نمایش داده می‌شود.

نکته جالب این است که در صفحات استاتیک، این ویژگی تقریباً تأثیری ندارد، زیرا مرورگرها هوشمندانه تغییرات را جمع‌آوری کرده و به شکل chunks رندر می‌کنند و تصاویر در جریان اصلی رندر بلوکه نمی‌شوند.

* در Firefox به‌صورت پیش‌فرض async است.
* در Chrome پیش‌فرض sync است.
* در WebKit بیشتر مواقع sync است اما در بعضی استثناها async است.

بنابراین مرورگرها هنوز روی یک رفتار پیش‌فرض توافق ندارند.

---

### تفاوت واقعی هنگام استفاده از JavaScript

در SPAها (برنامه‌های تک‌صفحه‌ای) وقتی تصاویر توسط JS اضافه می‌شوند، تفاوت محسوس می‌شود:

* اگر داخل JS یک div با پس‌زمینه قرمز بسازید و بعد یک تصویر بزرگ داخل آن اضافه کنید:

* با sync → صفحه ممکن است کمی گیر کند زیرا مرورگر منتظر رمزگشایی تصویر می‌ماند.
* با async → ابتدا پس‌زمینه قرمز نمایش داده می‌شود و بعد تصویر رندر می‌شود، اما ممکن است موقعیت چشمک زدن ایجاد شود.

* مرورگرهای مدرن تصاویر خارج از viewport را تا زمانی که به آن‌ها اسکرول نشود، رمزگشایی نمی‌کنند تا حافظه اضافی مصرف نشود. اما اگر صفحه پر از تصویر باشد و کاربر کلید End را بزند، ممکن است صفحه کمی گیر کند.

---

### توصیه‌ها

* اگر تصاویر را با JS بارگذاری می‌کنید، بهتر است از async استفاده کنید. این روش هم ناهمزمان است و هم قبل از رندر، تصویر آماده است.
* async مناسب زمانی است که متن صفحه مهم‌تر از تصاویر است. در این حالت دو مرحله رندر داریم ولی متن سریع‌تر نمایش داده می‌شود.
* برای بهینه‌سازی Core Web Vitals، به ویژه LCP**، بهتر است مقادیر مختلف را امتحان کنید. هرچند intuitively به نظر می‌رسد `sync` بهتر باشد، اما مرورگرها هوشمند هستند و باید تست و مقایسه کنید.
* اگر روی بهینه‌سازی رمزگشایی تصاویر کار می‌کنید، یا سایتتان از قبل عالی است، یا بهتر است روی مسائل مفیدتری مثل **بارگذاری تنبل تصاویر
و بهینه‌سازی خود تصاویر تمرکز کنید.

---

منبع اصلی: [TuneTheWeb](https://www.tunetheweb.com/blog/what-does-the-image-decoding-attribute-actually-do/)


#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
2
در media queries نمی‌توان از ویژگی‌های CSS (@property) استفاده کرد، اما راه‌های جایگزینی وجود دارد از طریق container queries.

@property --inline-size-s {
syntax: "<length-percentage>";
inherits: true;
initial-value: ۱۰۰vi;
}

:root {
--breakpoint-s: ۴۸em;
--inline-size-s: min(var(--breakpoint-s), ۱۰۰vi);
}

body {
background-color: var(--bg-color);

--bg-color: oklch(۰.۹۴ ۰.۰۱ ۹۹);

@container style(--inline-size-s: var(--breakpoint-s)) {
--bg-color: oklch(۰.۸۷ ۰.۲۱ ۹۵.۸۲);
}
}



#️⃣#tip #css
👥@IR_javascript_group
🆔@IR_javascript
👍1
در عنصر <link rel="stylesheet"> می‌توان ویژگی media را با یک عبارت مشابه آنچه در دستور @media استفاده می‌شود، تعیین کرد. مرورگر این عبارت رسانه‌ای را با محیط فعلی تطبیق می‌دهد و نتیجه‌ی آن بر نحوه‌ی بارگذاری فایل استایل تأثیر می‌گذارد:
<link
rel="stylesheet"
href="mobile.css"
media="(width < 600px)"
>

اگر شرط برقرار نباشد، فایل سبک با اولویت پایین و به‌صورت ناهم‌زمان (بدون مسدود کردن فرآیند رندر) بارگذاری می‌شود، اما خود استایل‌ها اعمال نخواهند شد.

#️⃣#tip #css
👥@IR_javascript_group
🆔@IR_javascript
👍3
بارگذاری فایل‌های CSS در لایه‌های مجزا با استفاده از ‎@import
<style>
@import url('utils.css') layer(utils);
</style>


مرورگر فایل utils.css را بارگذاری کرده و آن را در لایه‌ای با نام utils قرار می‌دهد. این کار امکان کنترل ترتیب و اولویت آبشاریِ سبک‌های این فایل نسبت به سایر لایه‌ها را فراهم می‌آورد — یعنی می‌توان اولویت آن را نسبت به فایل‌های دیگر بالا برد یا پایین آورد.

با این حال، دستور @import از نظر کارایی انتخاب مطلوبی نیست و معمولاً توصیه می‌شود از آن پرهیز شود، زیرا وجود `@import`های تو‌در‌تو موجب می‌شود فایل‌های سبک به‌صورت متوالی و نه موازی بارگذاری شوند.




#️⃣#tip #css
👥@IR_javascript_group
🆔@IR_javascript
همه‌ی فضاهای ذخیره‌سازی مثل هم نیستند؛ با «سطل‌های ذخیره‌سازی» آشنا شوید

وقتی حافظه‌ی دستگاه کاربر تمام می‌شود، داده‌هایی که با APIهایی مثل IndexedDB یا localStorage ذخیره شده‌اند، بی‌اختیار حذف می‌شوند و کاربر نمی‌تواند جلویش را بگیرد. راه فعلی برای «دائمی» کردن این است که متد persist() را صدا بزنیم:
const persisted = await navigator.storage.persist();
if (persisted) {
/* حافظه فقط با دستور مستقیم کاربر پاک می‌شود. */
}


این روش «همه یا هیچ» است؛ نمی‌توانید بگویید «فقط فلان داده مهم بماند». همه‌چیز در یک سطل ذخیره‌سازی واحد می‌ریزد.
API سطل‌های ذخیره‌سازی (Storage Buckets API)
ایده‌ی اصلی این است که سایت‌ها بتوانند چند سطل (bucket) جداگانه بسازند؛ مرورگر می‌تواند هر سطل را مستقل از بقیه حذف کند. بدین‌ترتیب توسعه‌دهنده می‌گوید «اگر مجبور به پاک‌کردن شدی، اول سراغ این سطل برو، آن یکی را آخرش بگذار».
مثال عملی
فرض کنید یک برنامه‌ی ایمیل داریم. از دست رفتن پیش‌نویس‌های ذخیره‌نشده روی دستگاه فاجعه است، اما اگر ایمیل‌های قدیمیِ Inbox حذف شوند چندان مهم نیست، چون روی سرور باقی‌مانده‌اند.

چطور از API استفاده کنیم؟
// سطل پیش‌نویس‌ها که فقط روی کلاینت است
const draftsBucket = await navigator.storageBuckets.open('drafts', {
durability: 'strict', // یا 'relaxed'
persisted: true, // یا false
});

‏دو پارامتر اختیاری می‌توان داد:
persisted: false (پیش‌فرض) یا true
durability: 'relaxed' (پیش‌فرض) یا 'strict'
'strict': در برابر قطع برق ایمن‌تر است؛ ممکن است سرعت نوشتن کم شود، باتری بیشتر مصرف کند و عمر حافظه‌ی فیزیکی کوتاه‌تر شود.
'relaxed': در صورت قطع برق ممکن است چند ثانیه‌ی آخر اطلاعات از بین برود؛ در عوض نوشتن سریع‌تر و دوام باتری و حافظه‌ی بیشتر است.

دسترسی به APIهای حافظه از داخل هر سطل
هر سطل به همان APIهای همیشگی (IndexedDB، Cache، File و …) وصل است؛ فقط ورودی از طریق خود سطل انجام می‌شود.
const inboxDb = await new Promise((resolve, reject) => {
const request = inboxBucket.indexedDB.open('messages');
request.onupgradeneeded = () => { /* کد مهاجرت */ };
request.onsuccess = () => resolve(request.result);
request.onerror = () => reject(request.error);
});

🔗https://developer.chrome.com/docs/web-platform/storage-buckets
#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript