Code Module | کد ماژول
1.91K subscribers
357 photos
42 videos
6 files
355 links
Hello World 🌎

<> Earth is programmable if you code it </>

Group 👇🏻
@CodeModuleGap

Contact Us 👇🏻
@MrShahiin
@neoMahan
Download Telegram
معرفی چند عملگر جاوا اسکریپتی که احتمالا از کاربرد اون بی خبری! ✌️


🔵عملگر in

اولین عملگری که قراره بررسی کنیم عملگر in هست که با استفاده از این عملگر میتونیم بررسی کنیم که آیا یک key (همان نام خاصیت ها در آبجکت های ما) در شی ما وجود داره یا نه:

const obj = {
name: ″shahin″
id: 1
}

if (″name″ in obj) {
console.log(″name is exist″)
}



🔵عملگر void

عملگر void کلیدواژه‌ای هست که یک گزاره رو ارزیابی می‌کنه و در نهایت مقدار undefined و برگشت میده. به مثال زیر توجه کنید:

   logger() { 
return 89
}
}

const d = new D

log(void d.logger()) // unde


همونطور که می‌بینید متد لاگر باید مقدار 89 رو برگشت بده، اما کلیدواژه void اونو تهی می‌کنه و به جای مقدار اصلی، مقدار تعریف نشده بازگشت میده. عملگر void موقعی استفاده میشه که مطمئن بشیم یک مقدار تعریف نشده واقعی به دست میاریم.


🔵عملگر delete

ساده‌ترین روش برای حذف مقداری از آرایه، استفاده از کلیدواژه Delete هست. برای این کار فقط به نام متغیر و ایندکسی که می‌خواید پاک کنید، نیاز دارید:

let numbers = [1,2,3,4]; 
delete numbers[1];
console.log(numbers); // [1, undefined, 3, 4]


البته در زمان استفاده از این روش باید مراقب باشید، زیرا گرچه این متد ساده به نظر میاد، اما در اغلب موارد موجب بروز سردرگمی میشه.


#operators #javascript
@CodeModule
Please open Telegram to view this post
VIEW IN TELEGRAM
4🔥3👌3
۷۰ سوال مصاحبه ای جاوا اسکریپت و میتونید تو pdf زیر مشاهده کنید⬇️

https://lnkd.in/eHEaJtH6

#javascript
@CodeModule
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥4❤‍🔥2👌2
آشنایی با weakSet و weakMap در ✌️

در جاوا اسکریپ دو تا ساختمان داده ی دیگه به اسم های WeakMap و WeakSet وجود داره که مشابه Map و Set هستن، با این تفاوت که تنها Object و آرایه و Non-Registered Symbol ها رو به عنوان Key قبول می کنند، اینجوری وقتی که Key مقدار Null بگیره از طریف WeakMap یا WeakSet هم قابل دسترسی نخواهد بود و Garbage-Collector محتوای اون رو از حافظه پاک میکنه.

مثالی از WeakMap:

let weakMap = new WeakMap();

let key1 = {id: 1};
let key2 = {id: 2};
let key3 = {id: 3};

weakMap.set(key1, "Value associated with key1");
weakMap.set(key2, "Value associated with key2");

console.log(weakMap.get(key1)); // Output: Value associated with key1

key1 = null; // حذف مرجع key1

// حالا حافظه رو بررسی کنید، ممکنه مقدار مرتبط با key1 حذف بشه چون دیگه هیچ مرجعی بهش اشاره نمی‌کنه


مثالی از WeakSet:

let weakSet = new WeakSet();

let obj1 = {name: "Alice"};
let obj2 = {name: "Bob"};
let obj3 = {name: "Charlie"};

weakSet.add(obj1);
weakSet.add(obj2);

console.log(weakSet.has(obj1)); // Output: true

obj1 = null; // حذف مرجع obj1

// حالا حافظه رو بررسی کنید، ممکنه obj1 از WeakSet حذف بشه چون دیگه هیچ مرجعی بهش اشاره نمی‌کنه


در کل توی پروژه های بزرگ که بهینه سازی در حد چند خط هم مهمه از این دو ساختار استفاده میشه.
مثال و اطلاعات بیشتر و میتونید تو داکیومنت زیر مطالعه کنید⬇️

Document 🌐

#javascript #weakset #weakmap
@CodeModule
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥3👌2
بررسی برخی فیچر های جدید جاوا اسکریپت (ES14) ✌️

اکما اسکریپت ۱۴ موجی از ویژگی‌های هیجان‌انگیز و در سال ۲۰۲۳ به نمایش گذاشت تا تجربه‌ی بهتری از برنامه نویسی با جاوا اسکریپت داشته باشید.

تو این پست برخی از متد های جدیدی که به جاوااسکریپت اضافه شده رو بررسی میکنیم.

1⃣ متد findLast
این متد در پروتوتایپ تمامی آرایه‌ ها قابل دسترسی هست (به عنوان مثال Array.prototype.findLast) و به طور مشابه به متد find عمل می‌کنه و برای یافتن یک عضو در آرایه استفاده میشه. با این تفاوت که جستجو رو از انتهای آرایه شروع می‌کنه.
const array1 = [5, 12, 50, 100, 44];const found = array1.findLast((element) => element > 45);
console.log(found);//Output: 100


2⃣متد toSorted
این متد نیز مشابه متد sort هست. این دو متد برای مرتب‌سازی اعضای یک آرایه استفاده میشن، با این تفاوت که متد toSorted آرایه اصلی و تغییر نمیده و خروجی اون یک آرایه جدید از اعضای مرتب‌شده هست.
const sortedNumbers = numbers.toSorted((a, b) => a - b) 
console.log(sortedNumbers) // Output: [1, 2, 3, 4, 5]

// common mistake using numbers
const nums2 = [0, 15, 5, 10, 20]
const sortedNums2 = nums2.toSorted()
console.log(sortedNums2) // Output: [0, 10, 15, 20, 5]


3⃣ متد toReversed
این متد نیز مشابه متد reverse عمل می‌کنه که برای معکوس کردن اعضای یک آرایه استفاده می‌شود، با این تفاوت که متد toReversed آرایهٔ اصلی و تغییر نمیده، بلکه خروجی اون یک آرایه جدید از اعضای معکوس شده هست.
const originalArray = [1, 2, 3, 4, 5];
// toReversed
const newArray = originalArray.toReversed();
console.log(originalArray); // Output: [1, 2, 3, 4, 5] the array is unmodified
console.log(newArray); // Output:[5, 4, 3, 2, 1]


4⃣ متد with
این متد به ما اجازه میده که یک عضو از آرایه رو با یک مقدار دیگه جایگزین کنیم، بدون اینکه آرایه اصلی و تغییر بدیم. این متد دو ورودی می‌گیره: ورودی اول که شماره ایندکس مورد نظر برای جایگزینی هست، و ورودی دوم مقدار جدید مورد نظر هست.
const numbers = [1, 2, 9999, 4]; 
const result = numbers.with(2, 3);
console.log(result); // [1, 2, 3, 4]


5⃣متد groupBy
با استفاده از متد groupBy، می‌تونیم اعضای یک آرایه رو بر اساس یک ویژگی مشترک بین آن‌ها گروه‌بندی کنیم. نکته‌ای که درباره‌ی groupBy وجود داره اینه که بر خلاف متدهای بالا، این متد به صورت استاتیک در دسترس، و مستقیماً از شیء Object Global قابل دسترسی هست.
 const inventory = [ 
{ name: &quotasparagus&quot, type: &quotvegetables&quot, quantity: 5 },
{ name: &quotbananas&quot, type: &quotfruit&quot, quantity: 0 },
{ name: &quotgoat&quot, type: &quotmeat&quot, quantity: 23 },
]

function myCallback({ quantity }) {
return quantity > 5 ? &quotok&quot : &quotrestock&quot
}

const result2 = Object.groupBy(inventory, myCallback);


#javascript #es14
@CodeModule
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥53❤‍🔥2👌2
آقای صدا، Howler.js 🔊

کتابخانه Howler.js، یک کتابخانه صدا هست که کار کردن با صدا رو در JavaScript و در تمام پلتفرم‌ها، ساده و قابل اطمینان می‌کنه.

این کتابخانه به شما در مواردی مثل پخش صدا و اضافه کردن افکت های صوتی به وب سایت، کمک میکنه. به عنوان مثال پخش صدا زمانی که شما یک پیغام خطا یا یک پیام دیگر رو دریافت میکنید. این قابلیت ها خیلی راحت و با چند خط کد توسط howler در اختیار ما قرار میگیره. حتی میتونید با استفاده از این کتابخانه یک پلیر موزیک هم داشته باشید 💀


ویژگی های کتابخانه Howler.js ⬇️


🔵پشتیبانی از پخش صداهای مختلف مثل MP3، WAV و OGG

🔵امکان به کار گیری بسیار ساده برای پخش، توقف، توقف موقت و مکث از طریق رابط کاربری خط فرمان

🔵پشتیبانی از قابلیت‌های پیشرفته مثل استفاده از صداها به صورت پویا، تنظیم میزان صدا و موقعیت در صدا، اعمال افکت‌های صوتی و زمان‌بندی دقیق

🔵معماری ماژولار Howler.js به شما کمک میکنه تا به سادگی از این کتابخانه استفاده، و اونو گسترش بدید، در نتیجه میتونید امکانات سفارشی بیشتری اضافه کنید.

پیشنهاد میکنم یه سر به داکیومنت این کتابخانه جذاب بزنید ⚡️

Document 🌐

#howler #javascript
@CodeModule
Please open Telegram to view this post
VIEW IN TELEGRAM
❤‍🔥10👌5🔥4😁2
با کتابخانه Parallax بیشتر آشنا بشید 🔥

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


برخی ویژگی‌های Parallax.js⬇️

🔵سبک و کم‌حجم

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

🔵پیاده‌سازی آسان

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

🔵سازگاری با مرورگرها

این کتابخانه با اکثر مرورگرهای مدرن سازگاره، بنابراین نیازی به نگرانی در مورد ناسازگاری مرورگرها نیست.

🔵پشتیبانی از عناصر مختلف

از Parallax.js برای ایجاد افکت در تصاویر، متون، ویدئوها و سایر عناصر HTML، میشه استفاده کرد.

🔵تنظیمات انعطاف‌پذیر

این کتابخانه دارای تنظیمات مختلفی هست که به دولوپرا اجازه میده تا رفتار و ظاهر افکت‌ها رو به راحتی کاستوم کنن.


برای کسب اطلاعات بیشتر و دسترسی به مستندات کامل، می‌تونید به داکیومنت این کتابخانه مراجعه کنید ⚡️

Document 🌐

#parallax #javascript
@CodeMoule
Please open Telegram to view this post
VIEW IN TELEGRAM
6🔥3
استایل‌ دادن به لاگ‌های جاوا اسکریپت در کنسول ✌️

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

کد زیر رو در نظر بگیرید⬇️

console.log("%c%s", 
"color: red; background: yellow; font-size: 24px;",
″CodeModule!");


اولین آرگومان ورودی یعنی (%c%s) استایل متن رو مشخص می‌کنه، دومین آرگومان رنگ رو تنظیم کرده که در کد بالا red (قرمز) تعیین شده. سومین آرگومان بک‌گراند رو مشخص می‌کنه و آرگومان های بعدی، به ترتیب سایز نوشته و خود نوشته هستند. اگه این کد رو در کنسول مرورگر اجرا کنید، کلمه CodeModule به‌ رنگ قرمز، با بک‌گراند زرد و فونت نسبتاً بزرگی چاپ میشه. استایل های دیگه ای هم میتونیم واسه لاگ هامون در نظر بگیریم و ترتیب آرگومان های استایل دهی اصلا مهم نیست.

برای مثال :

let StylesArray=[ 
'background-color: #f0c807',
'border: 1ps solid red',
'padding: 10px 20px',
'font-size: 10px',
].join(';')
console.log('%c CodeModule',StylesArray)

با استفاده از این ترفند، میتونید لاگ های کارآمد تر و زیبا تری داشته باشید 🔥

#javascript
@CodeModule
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥7😁1👌1
با Sinon.js دیگه نگران عملکرد کدتون نباشید!⚡️

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

اما تخصصی تر ‏Sinon.js واقعا چیه؟

‌‌‌‌‌‏Sinon.js یک کتابخانه هست که مجموعه ای از ویژگی ها برای تست کد ارائه میده، به ویژه برای تست کدهای ناهمزمان و برای ماک کردن وابستگی ها در برنامه شما مفیده، و میتونید ازش برای هر چارچوب تستی مثل Jasmine یا QUnit و... استفاده کنید.

چرا از Sinon.js استفاده کنیم؟

🔵قابلیت اطمینان تست بهبودیافته

‏Sinon.js به جداسازی کد تحت آزمایش کمک میکنه، تا اطمینان حاصل بشه که تست های ما تحت تأثیر عوامل خارجی قرار نمیگیرن.

🔵پوشش کد بهتر

‏Sinon.js آزمایش کامل همه مسیرهای کد، از جمله مدیریت خطا و edge cases رو امکان پذیر میکنه.

🔵وضوح تست بهبودیافته

ویژگی های این کتابخانه مثل spies و stubs، تست ها رو خواناتر و قابل درک تر میکنه.

🔵تست ناهمزمان ساده

‏Sinon.js با ویژگی هایی مانند تایمر های جعلی، آزمایش کدهای متکی بر time-based events رو آسون تر میکنه.


‏به صورت کلی، Sinon.js یک ابزار قدرتمنده که میتونه مجموعه تست های جاوا اسکریپتی شما رو تا حد زیادی بهبود ببخشه. برای کسب اطلاعات بیشتر به وب سایت رسمی Sinon.js مراجعه کنید.

#sinonjs #javascript
@CodeModule
Please open Telegram to view this post
VIEW IN TELEGRAM
7🔥2👌2
what the فاز javascript? ✌️

همونطور که میدونید، جاوااسکریپت یه سری منطق های عجیب و غریب داره که بعضی اوقات ممکنه مشکل ساز باشه.

سایت زیر اومده همه این باگ یا بی منطقی هارو جمع کرده، و به صورت لیست نمایش داده :))

🌐Website

#javascript
@CodeModule
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥17👌32
دنبال چلنج‌های جاوااسکریپتی هستی؟ ✌️

در این پست ۵ سایت کاربردی بهتون معرفی میکنم، که چلنج های جاوااسکریپتی سطح بندی شده بهتون ارائه میده. با استفاده از این سایت ها، میتونید دانش خودتون رو محک بزنید و اگه کم و کسری باشه درستش کنید 🦦

🔵leetcode

🔵jschallenger

🔵codedamn

🔵edabit

🔵jscodebox


#javascript #challenges
@CodeModule
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥104😁1👌1
‏AbortController در جاوااسکریپت ✌️

یکی از بزرگترین فاکتورهایی که کمک می‌کنه یک برنامهٔ بهینه و سریع داشته باشیم، اینه که بدونیم چطوری یک عملیات Async رو توی برنامه شروع، و اون‌ رو به پایان برسونیم. در حالت عادی ما عملیات مد نظرمون رو شروع می‌کنیم و بعد از چند لحظه پاسخ عملیات بهمون برمی‌گرده. پس عملیات به طور خودکار به پایان میرسه و به طور کلی، شروع این عملیات به دست خودمونه، اما پایانش خیر!

AbortController چیه؟ 🤔

‏AbortController یک قابلیته که اجازه میده خیلی راحت بتونیم یک یا چند عملیات Async رو در زمان لزوم متوقف کنیم.

فرض کنید می‌خوایم اطلاعاتی روی سرور آپلود کنیم:
(async function () { 
const res = await fetch('/upload', ... );
const data = await res.json();

return data;
})();

گاهی اوقات می‌بینیم که آپلود بیش از حد معمول طول می‌کشه و می‌خوایم اون رو کنسل کنیم تا برای مثال، دکمه‌ای تحت عنوان «تلاش مجدد» نشون بدیم تا کاربر بیش از اندازه منتظر نمونه. fetch به تنهایی چنین قابلیتی رو نداره. اما برای حل این مسئله AbortController به کارمون میاد.

برای اینکه بتونیم عملیات مد نظرمون رو کنترل کنیم، ابتدا باید با استفاده از AbortController یک کنترلر بسازیم:

const controller = new AbortController(); 

همه کنترلرها یک پراپرتی به اسم signal دارن، که به عنوان یک رابط بین کنترلر و عملیاتی که می‌خوایم اون رو کنسل کنیم هست.


مرحلهٔ بعد اینه که این کنترلر رو به شکل زیر به fetch بشناسونیم. آرگومان دوم fetch که یک آبجکت برای کانفیگ کردن این درخواست هست، یک پراپرتی به اسم signal داره. مقدار اون رو برابر با پراپرتی signal از کنترلر قرار میدیم:

const controller = new AbortController(); 

(async function () {
const res = await fetch('/upload', {
// ...
signal: controller.signal,
});

const data = await res.json();

return data;
})();

حالا هر زمانی که لازم داشتیم می‌تونیم این عملیات رو کنسل کنیم. برای این کار کافیه متد abort از کنترلر رو صدا بزنیم:
const controller = new AbortController(); 

document.getElementById("cancel").onclick = () => {
controller.abort();
}


به طور کلی، AbortController یک قابلیت کاربردی توی جاوااسکریپت هست که با استفاده اون خیلی راحت می‌تونیم یک یا چند عملیات Async رو در زمان لزوم متوقف کنیم. برای کسب اطلاعات و مشاهده نمونه مثال های بیشتر، این مقاله رو مطالعه کنید.

#javascript
@CodeModule
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥173
با Reflect در جاوااسکریپت بیشتر آشنا بشید ✌️

آبجکت یا شئ Reflect، شامل متدهای استاتیک برای فراخوانی متدهای داخلی interceptable اشیاء جاوااسکریپته. برخلاف اکثر گلوبال آبجکت ها، Reflect یک constructor نیست، یعنی شما نمی‌تونید از اون با اوپراتور new استفاده کنید یا شیء Reflect رو به عنوان یک تابع کال کنید. تمام ویژگی‌ها و متدهای Reflect استاتیک هستن (مثل آبجکت Math).

آبجکت Reflect مجموعه‌ای از توابع استاتیک رو فراهم میکنه که نام‌های مشابهی با متدهای هندلر پروکسی دارن.

مهم ترین استفاده ای که از Reflect میتونیم کنیم، اینه که default behavior رو در traps های (تابعی که رفتار متد داخلی مربوط به شیء یا آبجکتو تعریف می‌کنه) هندلر پروکسی مشخص کنیم.

یک trap برای متوقف کردن یک عملیات بر روی یک آبجکت استفاده میشه. برای مثال کدی که در خط های پایین تر میبینید، یک پروکسی با trap یک deleteProperty ایجاد می‌کنه که متد داخلی [[Delete]] رو متوقف می‌کنه. ()Reflect.deleteProperty برای فراخوانی رفتار پیش‌فرض [[Delete]] بر روی targetObject به‌طور مستقیم استفاده میشه، که میتونید اونو با delete هم جایگزین کنید.

const p = new Proxy({}, {
    deleteProperty(targetObject, property) {
      // Custom functionality: log the deletion
      console.log("Deleting property:", property);

      // Execute the default introspection behavior
      return Reflect.deleteProperty(targetObject, property);
    },
  },
);


🚀متدهای Reflect کنترل بیشتری بر نحوه فراخوانی متدهای داخلی فراهم میکنن. برای مثال، ()Reflect.construct تنها راهیه که میتونید یک تابع تارگت رو با یک مقدار خاص برای new.target بسازید.

اگر از اپراتور new برای فراخوانی یک تابع استفاده کنید، مقدار new.target همیشه خود تابع خواهد بود. این موضوع تأثیرات مهمی بر روی subClass ها داره. برای مثال، ()Reflect.get به شما اجازه میده تا یک getter رو با یک مقدار this کاستوم اجرا کنید، در حالی که دسترسی به ویژگی‌ها، همیشه از شیء فعلی به عنوان مقدار this استفاده می‌کنه.

تقریباً رفتار هر متد Reflect رو میشه با بعضی دیگه از سینتکس‌ها یا متدها انجام داد. بعضی از این متدها، متدهای استاتیک هم اسم تو کلاس Object دارن، هرچند که تفاوت‌های ظریفی وجود داره.

برای کسب اطلاعات بیشتر و درک عمیق تر Reflect و static method هاش، میتونید به منبع زیر مراجعه کنید 🏖️

Document 🌕

#javascript #reflect
@CodeModule
Please open Telegram to view this post
VIEW IN TELEGRAM
6🔥3
الگوی Event Delegation چیه؟ ✌️

در این پست می‌خوایم با الگویی به نام Event Delegation آشنا بشیم که بهمون اجازه میده پروژه هایی سریع‌تر، خواناتر و با عملکرد بالاتری داشته باشیم.

اگه چندین المنت مشابه داشتیم و نیاز بود با یک رویداد خاص (مثلاً keyup) همهٔ این المنت‌ها رو مدیریت کنیم، این الگو با استفاده از قابلیت Event Propagation، بهمون اجازه میده تا با اضافه کردن هندلر (یا Listener) به المنت والد، بتونیم رویدادهای المنت‌های داخلی رو مدیریت کنیم. یعنی ما به جای اینکه برای تک تک این المنت‌ها هندلر بنویسیم، هندلر رو به المنت والد اضافه می‌کنیم.

بریم که این الگو رو پیاده‌سازی کنیم. المنت‌های زیر رو در نظر بگیرید ⬇️

<form> 
<input id="num-1" name="num-1">
<input id="num-2" name="num-2">
<input id="num-3" name="num-3">
<input id="num-4" name="num-4">
<input id="num-5" name="num-5">
<input id="num-6" name="num-6">
</form>

ما ابتدا برای المنت والد یعنی <form> یک ایونت keyUp تنظیم میکنیم:
document.querySelector('form').addEventListener('keyup', (event) => { 
console.log(event.target.value);
});


باید بدونیم که با این کد، رویداد keyup همهٔ المنت‌های داخلی فرم قابل مدیریت هست و با رخ دادن این رویداد، کدی که توی هندلر نوشتیم برای همهٔ المنت‌ها اجرا میشه، حتی برای ورودی‌های دیگه‌ای مثل textarea و checkbox. حالا اگه ما بخوایم فقط برای input های نوع text این رویداد رو مدیریت کنیم، باید توی هندلر این قضیه رو مدیریت و محدود کنیم و مشخص کنیم که دقیقاً با کدوم ورودی‌ها سر و کار داریم:

document.querySelector('form').addEventListener('keyup', (event) => { 
if (event.target.tagName === 'INPUT' && event.target.type === 'text') {
console.log(event.target);
}
});


حالا به راحتی می‌تونیم رویداد keyup همهٔ <input> ها رو مدیریت کنیم و حتی اگه ورودی‌هایی اضافه یا کم بشه، کدی که نوشتیم دیگه تغییری نمی‌کنه. برای کسب اطلاعات بیشتر این مقاله رو مطالعه کنید.

#javascript #eventDelegation
@CodeModule
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥143❤‍🔥1