<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"><channel><title>نوشته های Davood Habbabi</title><link>https://virgool.ir/feed/@i_am_davood</link><description>اگر وقت کنم چیزایی که یاد گرفتم رو می نویسم</description><language>fa</language><pubDate>2026-11-11 20:08:26</pubDate><image><url>https://files.virgool.ir/upload/users/61190/avatar/sQ7ORn.png</url><title>Davood Habbabi</title><link>https://virgool.ir/@i_am_davood</link></image><item><title>اصول SOLID؛ چطور کدمون رو تمیزتر و قابل نگهداری‌تر بنویسیم؟ 🧑‍💻</title><link>https://virgool.ir/@i_am_davood/اصول-solid-چطور-کدمون-رو-تمیزتر-و-قابل-نگهداری-تر-بنویسیم-🧑-joujqeignvgu</link><description>اصول SOLIDاگر با برنامه‌نویسی شی‌گرا کار کرده باشی، احتمالاً یه جایی به کدی رسیدی که تغییر دادن یه قسمت کوچیکش باعث میشه سه جای دیگه خراب بشه! 😐مثلاً یه کلاس داری که هم مسئول ارسال ایمیله، هم اطلاعات رو داخل دیتابیس ذخیره می‌کنه، هم لاگ می‌نویسه و هم گزارش تولید می‌کنه.بعد یکی میاد میگه:«فقط سیستم ارسال ایمیل رو تغییر بده.»و تو با خودت میگی:«فقط؟! 😂»اینجاست که اصول SOLID به کمکمون میان.SOLID مجموعه‌ای از ۵ اصل مهم در طراحی نرم‌افزاره که کمک می‌کنن کدمون:قابل نگهداری‌تر باشهراحت‌تر تغییر کنهتست‌پذیرتر باشهوابستگی‌های کمتری داشته باشهو در پروژه‌های بزرگ کمتر تبدیل به کابوس بشه 😄بیایم یکی‌یکی بررسیشون کنیم.S — Single Responsibility Principleاولین اصل میگه:هر کلاس باید فقط یک مسئولیت داشته باشه و فقط به یک دلیل تغییر کنه.فرض کن یه کلاس داریم که مسئول مدیریت کاربره:class User {&#xA;  createUser(user) {&#xA;    // ذخیره کاربر در دیتابیس&#xA;  }&#xA;&#xA;  sendEmail(user) {&#xA;    // ارسال ایمیل&#xA;  }&#xA;&#xA;  generateReport(user) {&#xA;    // ساخت گزارش&#xA;  }&#xA;}در نگاه اول شاید مشکلی نبینیم.ولی این کلاس الان چند مسئولیت مختلف داره:User&#xA; ├── مدیریت کاربر&#xA; ├── ارسال ایمیل&#xA; └── ساخت گزارشحالا اگر سیستم ایمیل تغییر کنه، باید کلاس User رو تغییر بدیم.اگر سیستم گزارش‌گیری تغییر کنه، باز باید همین کلاس رو تغییر بدیم.اگر دیتابیس عوض بشه، باز...یعنی یک کلاس برای چند دلیل مختلف ممکنه تغییر کنه.راه بهتر چیه؟مسئولیت‌ها رو جدا کنیم:class UserService {&#xA;  createUser(user) {&#xA;    // ذخیره کاربر&#xA;  }&#xA;}&#xA;&#xA;class EmailService {&#xA;  sendEmail(user) {&#xA;    // ارسال ایمیل&#xA;  }&#xA;}&#xA;&#xA;class ReportService {&#xA;  generateReport(user) {&#xA;    // ساخت گزارش&#xA;  }&#xA;}حالا هر کلاس یه کار مشخص انجام میده.یعنی:UserService&#xA;     ↓&#xA;مدیریت کاربر&#xA;&#xA;EmailService&#xA;     ↓&#xA;ارسال ایمیل&#xA;&#xA;ReportService&#xA;     ↓&#xA;گزارش‌گیریاین همون Single Responsibility Principle هست.O — Open/Closed Principleاصل دوم میگه:کلاس‌ها باید برای توسعه باز و برای تغییر بسته باشن.این جمله اولش یکم عجیب به نظر میاد. 😐یعنی چی؟یعنی وقتی می‌خوایم قابلیت جدیدی اضافه کنیم، بهتره مجبور نباشیم کد قبلی رو مدام تغییر بدیم.فرض کن سیستم پرداخت داریم:class Payment {&#xA;  pay(type) {&#xA;    if (type === &#34;card&#34;) {&#xA;      // پرداخت با کارت&#xA;    }&#xA;&#xA;    if (type === &#34;paypal&#34;) {&#xA;      // پرداخت با PayPal&#xA;    }&#xA;  }&#xA;}حالا فردا می‌خوایم پرداخت با:Bitcoin&#xA;Apple Pay&#xA;Google Payهم اضافه کنیم.پس دوباره میریم داخل همین کلاس و کلی if اضافه می‌کنیم:if (type === &#34;bitcoin&#34;) {&#xA;  // ...&#xA;}&#xA;&#xA;if (type === &#34;applepay&#34;) {&#xA;  // ...&#xA;}هر بار که قابلیت جدید اضافه می‌کنیم، کد قبلی رو تغییر می‌دیم.یکی از راه‌های بهتر اینه که رفتارهای مختلف رو از هم جدا کنیم:class CardPayment {&#xA;  pay() {&#xA;    console.log(&#34;Payment with card&#34;);&#xA;  }&#xA;}&#xA;&#xA;class PaypalPayment {&#xA;  pay() {&#xA;    console.log(&#34;Payment with PayPal&#34;);&#xA;  }&#xA;}&#xA;&#xA;class BitcoinPayment {&#xA;  pay() {&#xA;    console.log(&#34;Payment with Bitcoin&#34;);&#xA;  }&#xA;}حالا اگر روش پرداخت جدیدی اضافه کنیم، لازم نیست کلاس‌های قبلی رو تغییر بدیم.فقط یک کلاس جدید اضافه می‌کنیم:class ApplePayPayment {&#xA;  pay() {&#xA;    console.log(&#34;Payment with Apple Pay&#34;);&#xA;  }&#xA;}یعنی سیستم برای توسعه بازه ولی برای تغییر کدهای قبلی تا حد ممکن بسته است.L — Liskov Substitution Principleاصل سوم یکی از اون اصل‌هاییه که اسمش کمی ترسناکه! 😂Liskov Substitution Principleمیگه:هر جا از کلاس والد استفاده می‌کنیم، باید بتونیم از کلاس فرزند هم استفاده کنیم، بدون اینکه رفتار برنامه خراب بشه.یه مثال معروف برای این موضوع، پرنده و پنگوئنه.فرض کنیم:class Bird {&#xA;  fly() {&#xA;    console.log(&#34;Flying...&#34;);&#xA;  }&#xA;}حالا می‌گیم:class Penguin extends Bird {&#xA;}مشکل چیه؟پنگوئن پرنده‌ست، ولی نمی‌تونه پرواز کنه.پس اگر این کار رو انجام بدیم:const bird = new Penguin();&#xA;&#xA;bird.fly();به مشکل می‌خوریم.چون قرارداد کلاس Bird گفته:هر پرنده‌ای باید قابلیت fly() داشته باشه.ولی Penguin نمی‌تونه این قرارداد رو رعایت کنه.راه بهتر اینه که طراحی رو اصلاح کنیم:class Bird {&#xA;}&#xA;&#xA;class FlyingBird extends Bird {&#xA;  fly() {&#xA;    console.log(&#34;Flying...&#34;);&#xA;  }&#xA;}&#xA;&#xA;class Penguin extends Bird {&#xA;}حالا:Bird&#xA;├── FlyingBird&#xA;│   ├── Eagle&#xA;│   └── Sparrow&#xA;│&#xA;└── Penguinدیگه پنگوئن مجبور نیست متدی داشته باشه که قادر به انجامش نیست.پس اصل Liskov بهمون میگه:وراثت نباید باعث بشه کلاس فرزند قرارداد کلاس والد رو نقض کنه.I — Interface Segregation Principleاصل چهارم میگه:بهتره کلاس‌ها مجبور نشن Interfaceهایی رو پیاده‌سازی کنن که بهشون نیازی ندارن.فرض کن یک Interface داریم:interface Worker {&#xA;  work();&#xA;  eat();&#xA;  sleep();&#xA;}حالا یک ربات داریم:class Robot implements Worker {&#xA;  work() {&#xA;    // کار کردن&#xA;  }&#xA;&#xA;  eat() {&#xA;    // 😐 ربات که غذا نمی‌خوره!&#xA;  }&#xA;&#xA;  sleep() {&#xA;    // 😐 ربات هم نمی‌خوابه!&#xA;  }&#xA;}اینجا طراحی خوبی نداریم.چون Robot مجبور شده متدهایی رو پیاده‌سازی کنه که اصلاً بهشون احتیاج نداره.بهتره Interface بزرگ رو به Interfaceهای کوچک‌تر تقسیم کنیم:interface Workable {&#xA;  work();&#xA;}&#xA;&#xA;interface Eatable {&#xA;  eat();&#xA;}&#xA;&#xA;interface Sleepable {&#xA;  sleep();&#xA;}حالا انسان می‌تونه:class Human implements Workable, Eatable, Sleepable {&#xA;}و ربات فقط:class Robot implements Workable {&#xA;}این دقیقاً مفهوم Interface Segregation هست.یعنی:Interfaceهای بزرگ و شلوغ رو به قراردادهای کوچک‌تر و تخصصی‌تر تقسیم کنیم.D — Dependency Inversion Principleو می‌رسیم به آخرین اصل:Dependency Inversion Principleاین اصل میگه:کلاس‌های سطح بالا نباید مستقیماً به جزئیات سطح پایین وابسته باشن؛ هر دو باید به abstraction وابسته باشن.فرض کن یک سرویس داریم:class MySQLDatabase {&#xA;  save(data) {&#xA;    console.log(&#34;Saving to MySQL&#34;);&#xA;  }&#xA;}&#xA;&#xA;class UserService {&#xA;  constructor() {&#xA;    this.database = new MySQLDatabase();&#xA;  }&#xA;&#xA;  saveUser(user) {&#xA;    this.database.save(user);&#xA;  }&#xA;}در اینجا UserService مستقیماً به MySQLDatabase وابسته شده.یعنی اگر فردا تصمیم بگیریم MySQL رو با MongoDB عوض کنیم، باید UserService رو تغییر بدیم.بهتره وابستگی رو از بیرون بهش بدیم:class UserService {&#xA;  constructor(database) {&#xA;    this.database = database;&#xA;  }&#xA;&#xA;  saveUser(user) {&#xA;    this.database.save(user);&#xA;  }&#xA;}حالا می‌تونیم هر دیتابیسی که قرارداد لازم رو داشته باشه بهش بدیم:const mysql = new MySQLDatabase();&#xA;&#xA;const userService = new UserService(mysql);یا:const mongo = new MongoDatabase();&#xA;&#xA;const userService = new UserService(mongo);در نتیجه UserService دیگه اهمیتی نمی‌ده اطلاعات دقیقاً کجا ذخیره میشن.فقط می‌دونه:Database&#xA;   ↓&#xA;save()این یعنی وابستگی ما به Abstraction هست، نه به یک پیاده‌سازی مشخص.پس SOLID در یک نگاه یعنی چی؟اگر بخوایم کل داستان رو خیلی خلاصه کنیم:S → یک کلاس، یک مسئولیت&#xA;&#xA;O → برای توسعه باز، برای تغییر بسته&#xA;&#xA;L → فرزند باید قابل جایگزینی با والد باشد&#xA;&#xA;I → Interfaceهای کوچک و تخصصی&#xA;&#xA;D → وابستگی به abstraction، نه implementationاما یه نکته مهم وجود داره.SOLID قانون آهنین برنامه‌نویسی نیست.قرار نیست هر جا یک کلاس دیدی، سریع پنج تا Interface و ده تا کلاس بسازی! 😂هدف SOLID اینه که وقتی پروژه بزرگ‌تر شد و نیازمندی‌ها تغییر کردن، کدمون کمتر به هم وابسته باشه و تغییر دادن یک بخش، کل سیستم رو به هم نریزه.در واقع میشه گفت:SOLID بیشتر از اینکه درباره نوشتن کد کمتر باشه، درباره نوشتن کدی هست که تغییر دادنش دردسر کمتری داشته باشه.</description><category>Davood Habbabi</category><author>Davood Habbabi</author><pubDate>Mon, 05 Oct 2026 12:03:54 +0330</pubDate></item><item><title>چرا CORS داریم؟</title><link>https://virgool.ir/@i_am_davood/چرا-cors-داریم-k92fpvjubfi2</link><description>چرا CORS داریم؟اگه با فرانت‌اند کار کرده باشی، احتمالاً یه روز با یه ارور خیلی اعصاب‌خردکن مواجه شدی:Blocked by CORS policyاولش احتمالاً با خودت گفتی: «خب بابا! من فقط می‌خوام یه API رو صدا بزنم، دیگه چرا گیر می‌دی؟!» 😐ولی واقعاً چرا مرورگر همچین کاری می‌کنه؟اصلاً CORS چرا به وجود اومده؟برای جواب دادن به این سؤال، باید اول یه چیز مهم‌تر رو بفهمیم: Same-Origin Policy.Same-Origin Policy چیه؟مرورگر از قدیم یه قانون امنیتی مهم داره به اسم Same-Origin Policy یا به اختصار SOP.ایده‌اش خیلی ساده‌ست:یه سایت نباید همین‌جوری بتونه به اطلاعات سایت‌های دیگه دسترسی داشته باشه.فرض کن وارد سایت بانک شدی:https://bank.com&#xA;و توی همون مرورگر هم وارد حساب بانکیت هستی.حالا یه سایت دیگه رو باز می‌کنی:https://evil.com&#xA;اگر مرورگر هیچ محدودیتی نداشت، سایت evil.com می‌تونست از طرف تو درخواست‌هایی به bank.com بفرسته و شاید به اطلاعات حساس حسابت دسترسی پیدا کنه.اینجا مرورگر میگه:«نه عزیزم، همچین خبری نیست!» 😄و جلوی دسترسی سایت‌ها به منابع Originهای دیگه رو می‌گیره.Origin اصلاً یعنی چی؟برای اینکه بفهمیم CORS چطوری کار می‌کنه، باید بدونیم Origin چیه.Origin از سه بخش تشکیل می‌شه:ProtocolHostPortمثلاً:https://example.com:443&#xA;اینجا داریم:Protocol → https&#xA;Host     → example.com&#xA;Port     → 443&#xA;حالا اینا رو ببین:https://example.com&#xA;https://api.example.com&#xA;http://example.com&#xA;https://example.com:3000&#xA;این‌ها Origin یکسانی ندارن.مثلاً این دو تا:https://example.com&#xA;https://api.example.com&#xA;چون Host متفاوت دارن، از نظر مرورگر دو Origin متفاوت محسوب می‌شن.پس مشکل CORS از کجا شروع میشه؟فرض کن فرانت‌اندت روی این آدرس اجرا شده:http://localhost:3000&#xA;و بک‌اندت روی این آدرس قرار داره:http://localhost:8000&#xA;تو از فرانت‌اند می‌خوای این درخواست رو بفرستی:fetch(&#34;http://localhost:8000/api/users&#34;)&#xA;از دید ما که هر دو روی localhost هستن و خیلی عادی به نظر می‌رسن.ولی مرورگر میگه:3000 ≠ 8000&#xA;پس این دو تا Origin متفاوتن.اینجاست که CORS وارد ماجرا میشه.CORS دقیقاً چیکار می‌کنه؟CORS مخفف این عبارته:Cross-Origin Resource Sharingیعنی:اشتراک‌گذاری منابع بین Originهای مختلفدر واقع CORS یه راه استاندارد به سرور میده که به مرورگر اعلام کنه:«من اجازه می‌دم فلان Origin به منابع من دسترسی داشته باشه.»مثلاً سرور می‌تونه در Response این Header رو برگردونه:Access-Control-Allow-Origin: http://localhost:3000&#xA;یعنی:«به درخواست‌هایی که از localhost:3000 میان اجازه دسترسی بده.»حالا مرورگر می‌بینه سرور اجازه داده و اجازه می‌ده JavaScript فرانت‌اند Response رو بخونه.یه نکته خیلی مهمCORS در اصل قانون سرور نیست؛ رفتار امنیتی مرورگره.یعنی این تصور اشتباهه که:«CORS اجازه نمی‌ده Request ارسال بشه.»در خیلی از درخواست‌ها، مرورگر ممکنه درخواست رو واقعاً به سرور بفرسته، ولی بعد اجازه نده JavaScript صفحه Response رو بخونه.این تفاوت خیلی مهمه.مثلاً ممکنه توی DevTools ببینی Request به سرور رفته، ولی مرورگر بعدش بهت بگه:Access to fetch at ... has been blocked by CORS policy&#xA;پس مشکل الزاماً این نیست که Request به سرور نرسیده؛ مشکل می‌تونه این باشه که مرورگر اجازه نداده کد JavaScript به Response دسترسی داشته باشه.چرا سرور باید اجازه بده؟چون مرورگر نمی‌تونه برای هر API حدس بزنه که چه کسی اجازه دسترسی داره.فرض کن یه API داریم:https://api.example.com/users&#xA;سرور می‌تونه بگه:Access-Control-Allow-Origin: https://mywebsite.com&#xA;یعنی:فقط سایت mywebsite.com اجازه داره Response این API رو از داخل مرورگر بخونه.ولی اگر سرور این Header رو نفرسته، مرورگر طبق قوانین CORS اجازه دسترسی JavaScript به Response رو نمی‌ده.Preflight چیه؟اینجا یکی از قسمت‌های جذاب CORS می‌رسیم: Preflight Request.بعضی درخواست‌های Cross-Origin قبل از اینکه Request اصلی ارسال بشه، یه درخواست OPTIONS می‌فرستن.مثلاً مرورگر می‌پرسه:OPTIONS /api/users&#xA;Origin: https://mywebsite.com&#xA;Access-Control-Request-Method: POST&#xA;Access-Control-Request-Headers: Content-Type&#xA;در واقع مرورگر داره از سرور می‌پرسه:«داداش، من از این Origin میام و می‌خوام با متد POST و این Headerها درخواست بزنم. اوکیه؟»سرور اگر مشکلی نداشته باشه، مثلاً جواب می‌ده:Access-Control-Allow-Origin: https://mywebsite.com&#xA;Access-Control-Allow-Methods: POST&#xA;Access-Control-Allow-Headers: Content-Type&#xA;بعد مرورگر میگه:«اوکی، بزن بریم.» 😎و Request اصلی رو ارسال می‌کنه.چرا همه Requestها Preflight ندارن؟چون بعضی درخواست‌ها اصطلاحاً Simple Request محسوب می‌شن و نیازی به Preflight ندارن.مثلاً یک GET ساده ممکنه بدون OPTIONS قبلی ارسال بشه.اما اگر شرایط درخواست از قوانین درخواست ساده خارج بشه، مرورگر ممکنه قبلش Preflight انجام بده.برای همین بعضی وقت‌ها توی Network می‌بینی:OPTIONS&#xA;POST&#xA;و میگی:«این OPTIONS دیگه از کجا پیداش شد؟!» 😂اون همون Preflight مربوط به CORSه.پس CORS برای اذیت کردن ما ساخته نشده!واقعیت اینه که CORS یکی از چیزهاییه که اول کار خیلی رو مخ به نظر میاد.ولی اگر CORS وجود نداشت، یه سایت مخرب می‌تونست خیلی راحت از داخل مرورگر کاربر به سرویس‌های دیگه درخواست بفرسته و Response اون‌ها رو بخونه.پس داستان اصلی اینه:Browser&#xA;   ↓&#xA;&#34;آیا این سایت اجازه داره؟&#34;&#xA;   ↓&#xA;Server&#xA;   ↓&#xA;&#34;آره، اجازه داره.&#34;&#xA;   ↓&#xA;Browser&#xA;   ↓&#xA;&#34;باشه، Response رو در اختیار JavaScript می‌ذارم.&#34;&#xA;در واقع CORS یه مکانیزم اجازه دادن کنترل‌شده روی محدودیت Same-Origin Policy محسوب می‌شه.CORS با Authentication چه فرقی داره؟این یکی هم خیلی مهمه.CORS نمیگه:«آیا این کاربر اجازه دسترسی به اطلاعات رو داره؟»این کار وظیفه Authentication و Authorization هست.CORS بیشتر میگه:«آیا JavaScriptای که از این Origin اجرا شده، اجازه داره Response این سرور رو بخونه؟»پس اینا دو موضوع جدا هستن.ممکنه CORS کاملاً درست تنظیم شده باشه، ولی کاربر Authentication نداشته باشه و API جواب 401 Unauthorized بده.برعکسش هم ممکنه Authentication درست باشه، ولی مرورگر به خاطر CORS اجازه دسترسی به Response رو نده.چرا Postman خطای CORS نمی‌ده؟اینجا یکی از سؤال‌های معروفه:«API توی Postman کار می‌کنه، ولی توی مرورگر CORS Error می‌گیرم. چرا؟»چون CORS یک مکانیزم مربوط به مرورگره.Postman مثل مرورگر رفتار نمی‌کنه و محدودیت‌های امنیتی مرورگر رو به همون شکل اعمال نمی‌کنه.پس ممکنه:Postman → API → OK ✅&#xA;&#xA;Browser → API → CORS Error ❌&#xA;این لزوماً به معنی خراب بودن API نیست.در نهایت CORS چرا داریم؟اگر بخوایم همه داستان رو در یک جمله خلاصه کنیم:CORS داریم تا مرورگر بتونه بین درخواست‌های Cross-Origin، دسترسی JavaScript به Responseها رو به شکل کنترل‌شده مدیریت کنه.بدون این محدودیت‌ها، یک سایت مخرب می‌تونست از داخل مرورگر کاربر به سرویس‌های مختلف درخواست بفرسته و اطلاعات Response رو بخونه.پس دفعه بعد که با این خطا مواجه شدی:Blocked by CORS policy&#xA;به جای اینکه بگی:«باز این CORS لعنتی!» 😂یادت باشه مرورگر داره میگه:«من فقط دارم مطمئن می‌شم این سایت واقعاً اجازه داره جواب این سرور رو بخونه.»و دقیقاً به همین دلیل، CORS وجود داره.</description><category>Davood Habbabi</category><author>Davood Habbabi</author><pubDate>Sun, 04 Oct 2026 12:02:23 +0330</pubDate></item><item><title>بررسی event propagation در جاوااسکریپت</title><link>https://virgool.ir/WebDevelopers/بررسی-event-propagation-در-جاوااسکریپت-zzywv0tqo3cp</link><description>مفهوم event propagation خیلی ساده و در عین حال کاربردیه و اگر ازش مطلع نباشیم واقعا ازار دهنده خواهد بود اگر بخوایم به زبان ساده این مفهوم رو توضیح بدیم در واقع وقتی یک ایونتی روی یک المت اتفاق می افته فقط روی همون یه دونه المنت اتفاق نمی افته بلکه توی المنت های والدش هم اتفاق می افته به عنوان مثال به کد زیر دقت کنید.&lt;div =&#34;log(div)&#34;&gt;&#xA;    &lt;p =&#34;log(p)&#34;&gt;&#xA;         This is P element&#xA;        &lt;span =&#34;log(span)&#34;&gt;&#xA;             This is span element&#xA;        &lt;/span&gt;&#xA;    &lt;/p&gt;&#xA;&lt;/div&gt;با توجه به کد بالا اگر فانکش log رو به صورت زیر در نظر بگیریم &#xA;function(text){&#xA;    console.log(text)&#xA;}وقتی روی نوشته  This is P element کلیک کنیم توقع داریم توی کنسول مقدار &#34;p&#34; رو ببینیم ولی اینطور نیست و ما به ترتیب دو مقدار p و div رو خواهیم دید دلیلش پدیده ای هست که بهش می گیم event bubbling تعریف event bubblingدر واقع وقتی یه ایونتی توی صفحه اتفاق می افته (مثلا کلیک) اون ایونت از المنت target (المنتی که ایونت از اون شروع شده) به سمت والد خودش حرکت می کنه تا به document و window برسه و اگر ما برای والد های المنت target ایونت تعریف کرده باشیم همه اون ها اجرا خواهند شد تعریف event capturingبه برعکس همین پدیده می گن event capturing در واقع مسیر حرکت ایونت ها برعکسه یعنی ایونت از window شروع می شه و به المنت target می رسه یعنی توی مثال بالا اگر event capturing اتفاق بیفته ما به ترتیب دو مقدار div و p رو خواهیم داشت (ترتیب مهمه)توی مرورگر ها به صورت پیشفرض event bubbling اتفاق می افته و برای این که بتونیم event capturing داشته باشیم باید ارگومان سوم تابع addeventlistener رو true کنیم به مثال دقت کنید element.addEventListener(&#34;click&#34;, log, true);و اگر بخوایم کلا event propagation اتفاق نیفته و جلوگیری بشه ازش باید از کد event.stopPropagation();استفاده کنیمامیدوارم مفید باشه :)آقا داود </description><category>Davood Habbabi</category><author>Davood Habbabi</author><pubDate>Wed, 16 Mar 2022 18:11:54 +0330</pubDate></item><item><title>بررسی الگوریتم مرتب سازی Selection Sort</title><link>https://virgool.ir/tomanfrontendteam/بررسی-الگوریتم-مرتب-سازی-selection-sort-nkkyx76ugqae</link><description>این نوع الگوریتم هم خیلی سادس و فهمیدنش اصلا کار سختی نیست به تصویر بالا دقت کنیدطبق این الگوریتم توی قدم اول میاد و اولین ایندکس از ارایه رو در نظر می گیره و توی بقیه ارایه می گرده دنبال کوچک ترین عدد که کوچک تر از ایندکس اول باشه رو پیدا می کنه وقتی که عددی پیدا کرد که کوچیک تر باشه میاد جای ایندکس اول و عدد کوچک تر رو عوض می کنه توی پالس بعدی ایندکس دوم رو در نظر می گیره و باز بررسی می کنه کوچک ترین عدد که کوچک تر از ایندکس دوم باشه رو پیدا می کنه و جاشونو عوض می کنه این روند به تعداد مقادیر موجود در ارایه ( arr.length) تکرار می شه تا ارایه مرتب بشهاگر دقت کنید خود به خود ارایه ما تبدیل به دو بخش مرتب شده و مرتب نشده از ایندکس صفر تا ایندکس اخر تقسیم می شه  این الگوریتم الگوریتم مرتب سازی درجا هستش و نیازی به اشغال حافظه بیشتر رو نداره و در همون ارایه مرتب سازی انجام می شه ولی پرفورمنس خوبی نداره و پیچیدگی زمانی این الگوریتم برابر با O(n^2) است.بریم کدش رو بررسی کنیم function selectionSort(arr) {&#xA;  for (let i = 0; i &lt; arr.length; i++) {&#xA;    let minIndex = i; //(1)&#xA;    for (let j = i + 1; j &lt; arr.length; j++) {&#xA;      if (arr[j] &lt; arr[minIndex]) {&#xA;        minIndex = j;&#xA;      }&#xA;    }&#xA;    if (i !== minIndex) { //(2)&#xA;      const lesser = arr[minIndex];&#xA;      arr[minIndex] = arr[i];&#xA;      arr[i] = lesser;&#xA;    }&#xA;  }&#xA;  return arr;&#xA; }خب خود کد تقریبا همه چیز رو گفته  و زیاد به توضیح نداره (1) در این بخش از طریق یه حلقه و یک متغییر کوچک ترین ایندکس بعد از ایندکس n رو پیدا می کنیم(2)در این بخش هم با استفاده از یک متغییر کمکی جای کوچکترین عدد رو با ایندکس فعلی عوض می کنیمامیدوارم مفید باشه :)آقا داود </description><category>Davood Habbabi</category><author>Davood Habbabi</author><pubDate>Sat, 24 Jul 2021 13:54:27 +0430</pubDate></item><item><title>الگوریتم Bubble Sort یا همون مرتب سازی حبابی</title><link>https://virgool.ir/tomanfrontendteam/الگوریتم-bubble-sort-یا-همون-مرتب-سازی-حبابی-nrtb8fbbtatg</link><description>این الگوریتم تقریبا ساده ترین راه برای مرتب سازی یک ارایه از اعداد یا رشته ها هستش نحوه کار کرد این الگوریتم به این نحوه که میاد ایندکس اول رو با ایندکس دوم مقایسه می کنه اگر عدد اول بزرگ تر بود جاشو با عدد دوم عوض می کنه اگر نه دست بهش نمی زنه و به همین نحو تا ایدکس اخر می ره یعنی چی ؟ به عکس پایین نگاه کنید ما اینجا یک ارایه از اعداد مثل ارایه پایین داریمlet array = [ 5 , 1 , 4 , 2 , 8 ]خب عکسو ببینید توی پالس اول 5 بزرگ تر از 1 هستش پس جاشو عوض می کنه خط بعدی باز 5 از 4 بزرگ تره جاشونو عوض می کنه خط سوم 5 از 2 بزرگ تره باز هم جا به جایی صورت می گیره حظ چهارم 5 از 8 کوچیک تره جا به جایی صورت نمی گیره و می ره برای پالس بعدی توی پالس بعدی هم همون مقایسه ها از اول تکرار می شه و این چرخه انقدر ادامه پیدا می کنه تا هیچ جا به جایی صورت نگیره خب به صورت تئوری فهمیدیم این الگوریتم به چه شکله حالا بیاید کد جاوااسکریپتیش رو بنویسیمfunction bubbleSort(array) {&#xA; &#x9;let swapped = true;                                       //(1)&#xA; &#x9;do {&#xA; &#x9;&#x9;swapped = false;&#xA; &#x9;&#x9;for (let j = 0; j &lt; array.length; j++) {&#xA; &#x9;&#x9;&#x9;if (array[j] &gt; array[j + 1]) {             //(2)&#xA; &#x9;&#x9;&#x9;&#x9;let temp = array[j];                 //(3)&#xA; &#x9;&#x9;&#x9;&#x9;array[j] = array[j + 1];&#xA; &#x9;&#x9;&#x9;&#x9;array[j + 1] = temp;&#xA; &#x9;&#x9;&#x9;&#x9;swapped = true;                    //(4)&#xA; &#x9;&#x9;&#x9;}&#xA; &#x9;&#x9;}&#xA; &#x9;}&#xA; while (swapped);&#xA; &#x9;return array;&#xA; }کد بالا رو ببینید(1)  اول اومدیم یه متغییر تعریف کردیم تا بتونیم تشخیص بدیم که ایا توی هر پالس جا به جایی صورت می گیره یا نه (2) شرط گذاشتیم که ایندکسمون با ایندکس بعدیش بزرگ تره یا نه و اگر بزرگ تر باشه جا به جایی انجام می شه در غیر این صورت هیچ اتفاقی نمی افته (3) حین جا به جایی ایندکس فعلی رو می ریزیم توی یک متغییر به اسم temp تا داشته باشیم و خط بعدش میایم ایندکس فعلی رو با اندکس بعدیش جا به جا می کنیم و مقدار temp رو می ریزیم تو ایندکس بعدی (4) وقتی شرط اجرا می شه در واقع یعنی یک جا به جایی صورت گرفته و بالاتر توضیح دادم که وقتی جا به جایی داشته باشیم به این معنی که پالس بعدی هم داریم و باید انقدر پالس ها رو اجرا کنیم تا هیچ جا به جایی اتفاق نیفته پس مقدار رو true می کنیم تا do while یک بار دیگه اجرا بشه پیچیدگی زمانی این الگوریتم توی بهترین حالت برابر (n)O هستش و در حالت متوسط و بد (n * n)O هستش و بهترین حالت وقتیه که ارایه از قبل مرتب شده باشه و بدترین حالت وقتیه که ارایه برعکس مرتب شده باشه که ذاتا پرفرمنس خوبی نداره و الگوریتم های بهتری (از نظر زمان) برای مرتب سازی وجود داره که توی پست های بعدی معرفی خواهم کرد این الگوریتم یک روش مرتب سازی درجا هستش یعنی برای مرتب سازی از فضای جانبی کمک نمی گیره و با جا به جا کردن ایندکس های خود ارایه اون ها رو مرتب می کنه امیدوارم مفید باشه :)آقا داود</description><category>Davood Habbabi</category><author>Davood Habbabi</author><pubDate>Tue, 20 Jul 2021 19:10:47 +0430</pubDate></item><item><title>شبه المنت ها و شبه کلاس ها در css</title><link>https://virgool.ir/Gajino-FrontEnd/شبه-المنت-ها-و-شبه-کلاس-ها-در-css-f0o4kwefwqdj</link><description>رفقا سلام امروز در خدمتتون هستم با معرفی نیم المنت ها و نیم کلاس های css امیدوارم به دردتون بخوره  1 . شبه المنت یا نیم المنت (pseudo elements)یه مفهومی توی css وجود داره به اسم شبه المنت یا نیم المنت به این صورت که یه سری المنت ها به صورت خارجی وجود ندارن ولی می شه بهشون با css استایل داد و یا اصلا به صورت المنت باهاشون رفتار کرد یا اصلا ایجادشون کرد مثلا :نیم المنت after :در واقع این بزرگوار میاد قبل از شروع المنت اصلی یه نیم المنت ایجاد می کنه می شه در حد تکست و فونت ایکون بهش محتوا داد و استایل های مختلف بهش داد نیم المنت before :این هم مثل after عمل می کنه با این تفاوت که بعد از المنت اصلی ایجاد می شه نیم المنت first-letter :همون طور که از اسمش پیداس میاد حرف اول المنت اصلی رو می گیره و شما می تونید مثل بقیه المنت ها بهش استایل بدیدنیم المنت first-line :ایشون هم خط اول رو هدف قرار می ده و می تونید خط اول المنت اصلی رو هر استایلی که بخواید بدید نیم المنت marker :در تگ های ol و ul وقتی که لیست ایجاد می کنید در کنار لیست ایتم ها یک علامت به صورت عددی یا ایکونی وجود داره با استفاده از نیم المنت marker می تونید به اون بخش استایل بدید نیم المنت selection :توی صفحات وب شما می تونید بخشی از متن رو سلکت کنید و روی اون بخش عملیات مختلف انجام بدید مثل کپی و پیست و هر عملیات دیگه ای با استفاده از این نیم المنت می تونید به بخش های سلکت شده توسط موس استایل های متفاوت بدید 2 . شبه کلاس یا نیم کلاس (pseudo classes)با استفاده از این شبه کلاس ها شما می تونید به حالت های خاصی از المنت اصلی استایل های مختلفی بدید به عنوان مثال وقتی که روی یک لینک کلیک کنید و نگهدارید (نیم کلاس active)یا وقتی که کرسر موس رو داخل یک تکست باکس قرار بدید (نیم کلاس focus )*** نکته : تعداد نیم کلاس ها خیلی زیاده من تو این مقاله چند تاییش رو اسم می برم و شما رو میسپارم به دست دوست خوبم w3schools ***نیم کلاس first-child :همون طور که از اسمش پیداست اولین فرزند المنت اصلی رو هدف قرار می ده نیم کلاس hover :این نیم کلاس حالتی رو هدف قرار می ده که نشانگر موس در لحظه روی المنت قرار گرفته باشه نیم کلاس root : مستقیما دایکیومنت اصلی رو هدف قرار می ده(اغلب متغیر های css هم توی همین تعریف می شه )نیم کلاس disabled :حالت غیر فعال المنت رو هدف قرار می ده (یعنی وقتی که اتربیوت disabled داخل المنت فعال باشه) نیم کلاس last-child :همون طور که از اسمش پیداست اخرین فرزند المنت اصلی رو هدف قرار می دهخلاصه شناختن این نیم کلاس ها و نیم المنت های خیلی مهم هستن و شما با دذونستن اینها می تونید بخش خیلی زیادی کد هاتون رو بهینه کنید لینک کامل نیم کلاس ها و نیم المنت ها اینجا هست می تونید خودتون بخونیدش : نیم المنت ها و نیم کلاس ها امیدوارم مفید باشه :)</description><category>Davood Habbabi</category><author>Davood Habbabi</author><pubDate>Wed, 05 May 2021 18:09:38 +0430</pubDate></item><item><title>روتینگ فارسی برای next js</title><link>https://virgool.ir/Gajino-FrontEnd/روتینگ-فارسی-برای-next-js-ibadhysd3l1u</link><description>اون دسته از عزیزانی که با next js کار کردن می دونن که روتینگ فارسی نداشت و کلی داستان داریم براش تا بتونیم روت های استاتیک و یا داینامیکی بسازیم یعنی اگر بخوایم داشته باشیم http://localhost:3000/سلامباید توی فایل هامون یه  سلام.jsایجاد کنیم و داخلش کدمون رو بنویسیم ولی خب به دلیل این که UTF-8 در فایل سیستم متفاوته با UTF-8 در url همچنان صفحه 404 خواهیم داشت یعنی چی ؟بذارید یه مثال بزنم کلمه &#34;سلام&#34; رو در زبان فارسی در نظر بگیرید این در محیط دسکتاپ برابر است با : \xd8\xb3\xd9\x84\xd8\xa7\xd9\x85ولی در url برابر است با :%D8%B3%D9%84%D8%A7%D9%85خب واضحه که این دو تا رشته با هم برابر نیستن پس وقتی ما در محیط دسکتاپ یه فایل ایجاد می کنیم next سعی می کنه http://localhost:3000/%D8%B3%D9%84%D8%A7%D9%85رو باز کنه در فایل سیستم دنبالش می گرده ولی پیدا نمی کنه چون در فایل سیستم چنین چیزی ذخیره شده http://localhost:3000/\xd8\xb3\xd9\x84\xd8\xa7\xd9\x85خب حالا فهمیدیم مشگل کجاس چطوری حلش کنیم ؟جناب next یه کانفیگی داره به اسم Rewrites که با استفاده از اون می تونیم بگیم از روی فایل سیستم تشخیص نده و فایل ها رو از اونجایی که ما می گیم بخونه در واقع روال قبلی next رو داره دور می زنه و این امکان رو به ما می ده تا بگیم تو کدوم روت چه فایلی رو بخونه بذارید با مثال بریم جلو :فرض کنید محتویات فایل next.config.js یه پروژه ای به این صورته :module.exports = {&#xA;  async rewrites() {&#xA;    return [&#xA;      {&#xA;        source: &#39;/about&#39;,&#xA;        destination: &#39;/&#39;,&#xA;      },&#xA;    ]&#xA;  },&#xA;}این یعنی محتویات صفحه http://localhost:3000/aboutداره از فایل index.js پروژه خونده می شه خب این دقیقا چیزیه که ما لازم داریم با یکم تغییرات بیاید برای http://localhost:3000/سلامامتحان کنیم یعنی :module.exports = {&#xA;  async rewrites() {&#xA;    return [&#xA;      {&#xA;        source:`/${encodeURI(&#34;سلام&#34;)}`,&#xA;        destination: &#39;/hello&#39;,&#xA;      },&#xA;    ]&#xA;  },&#xA;}اون /hello که می بینید در واقع یک فایل hello.js توی پوشه pages ساختیم و اون مقدار ${encodeURI(&#34;سلام&#34;)} دقیقا انکد شده &#34;سلام&#34; هستش این طوری پیج های غیر داینامیکی رو می تونیم به فارسی روت کنیم حالا بازم اگر لازم باشه همچین روتی داشته باشیم http://localhost:3000/سلام/hiباید داخل فایل  next.config.js براش کانفیگ کنیم تا بشناسه یعنی module.exports = {&#xA;  async rewrites() {&#xA;    return [&#xA;      {&#xA;        source:`/${encodeURI(&#34;سلام&#34;)}`,&#xA;        destination: &#39;/hello&#39;,&#xA;      },&#xA;      {&#xA;         source: &#39;/${encodeURI(&#34;سلام&#34;)}/hi&#39;,&#xA;         destination: &#39;/hello/hi&#39;,&#xA;       },&#xA;    ]&#xA;  },&#xA;}برای پیج های داینامیکی بعد از روت فارسی هم می تونیم اینطوری کانفیگ بنویسیم module.exports = {&#xA;  async rewrites() {&#xA;    return [&#xA;      {&#xA;        source: &#39;/${encodeURI(&#34;سلام&#34;)}&#39;,&#xA;        destination: &#39;/hello&#39;,&#xA;      },&#xA;      {&#xA;         source: &#39;/${encodeURI(&#34;سلام&#34;)}/:id&#39;,&#xA;         destination: &#39;/hello/:id&#39;,&#xA;       },&#xA;    ]&#xA;  },&#xA;}توجه کنید برای این که id رو بگیرید باید توی فولدر pages/hello یک فایل به اسم id].js] بسازیدامیدوارم مفید باشه :) </description><category>Davood Habbabi</category><author>Davood Habbabi</author><pubDate>Sun, 21 Feb 2021 15:57:32 +0330</pubDate></item><item><title>تفاوت بین var , let و const</title><link>https://virgool.ir/Gajino-FrontEnd/تفاوت-بین-var-let-و-const-anhomyulzce5</link><description>با اومدن es6 تعریف متغیر در جاوا اسکریپت تغییر کرد و یه کلید واژه به اسم let وارد جاوا اسکریپت شد فرق const با اون دو تای دیگه که مشخصه const همون طور که از اسمش پیداست یک مقدار ثابت هستش و طی برنامه نمی شه مقدارش رو تغییر داد ولی فرق های let و var :برای فهمیدن تفاوت های let و var باید یکم بیشتر راجع به scope ها بدونید در زمان های دور (es5) دو نوع scope داشتیم یا Global Scope بود یا Function Scope  از اسمشونم معلومه چیه دیگه یا مقادیر داخل function ها تعریف می شدن یا به صورت عمومی (که تعریف همچین متغییر هایی به دلیل پرفرمنس جیز بود و نباید انجامش می دادیم )وقتی که es6 اومد یه Scope جدید با خودش آورد به اسم Block Scope حالا بریم ببینیم فرقشون چیهنکته : در جاوااسکریپت هر {} یک بلوک محسوب می شود پس هر کدی که داخل {} قرار بگیرد داخل یک بلوک کد است لازم به ذکر است که Function Scope یک حالت خاص از Block Scope می باشد در واقع function Scope همان Block Scope است که به صورت function تعریف شده باشد نکته 2 : هر function Scope قطعا یک Block Scope است ولی لزوما همه Block Scope ها Function Scope نیستند تیکه کد پایین رو در نظر بگیرید var a = 40 &#xA;if(a &gt; 10){&#xA;   var a = 42;&#xA;}&#xA;console.log(a);&#xA;//output : 42به این می گن Global Scope یعنی به صورت عمومی در دسترس هستش که خب استفاده کردن ازش همچنان جیزه :)حالا اینو ببینید let a = 40;&#xA;if(a &gt; 10){&#xA;    let a = 42;&#xA; }&#xA;console.log(a);&#xA;//output : 40بیاین یه مثال ملموس تر بزنیم که هم Function Scope استفاده کرده باشیم هم block Scopeکد پایین رو ببینید &#xA;function (){&#xA;  let a = 11; &#xA;  var b = 12&#xA;   if(a &gt; 10 ){&#xA;       let a = 9;&#xA;       var b = 15;&#xA;       console.log(&#34;first log a &#34; , a); &#xA;       console.log(&#34;first log b&#34; , b);&#xA;   }&#xA;console.log(&#34;second log a&#34; , a);&#xA;console.log(&#34;second log b&#34; ,b);&#xA;//output :first log a 9  &#xA;//output :first log b 15&#xA;//output :second log a 11 &#xA;//output :second log b 15 &#xA;} چی شد ؟اساسی ترین فرق let و var همین هستش که let حوزش Block Scope هستش و var حوزش Function Scopeیعنی شما اگر مقداری که با let تعریف کردین داخل یه بلوک دیگه (مثل if , else , loop و ...) مجدد با همون نام تعریفش کنید و مقدار بهش بدین بیرون بلوک انگاری که هیچ کاری نکردین و تاثیری روی مقدار بیرون بلوک نخواهد داشت یه تفاوت دیگه هم let  و var دارندشما می تونی داخل حوزه var  مجدد با همون نام مقدار تعریف کنی ولی با let  نمی تونی یعنی چی ؟ کد پایین رو ببین :function (){&#xA;var a = 10;&#xA;var a = &#34;Hello World !&#34;&#xA;console.log(a);&#xA;//output : Hello World !&#xA;}ولی :function (){&#xA; let a = 10;&#xA; let a = &#34;Hello World !&#34;&#xA; console.log(a);&#xA; //output : SyntaxError: Identifier &#39;a&#39; has already been declared &#xA;}لازم به ذکره تمامی رفتار های const کاملا مشابه let هستش با این تفاوت که let طی برنامه می تونه مقدار دیگه ای براش جایگذین بشه ولی مقدار const قابل تغییر نیست یعنی :function (){&#xA;const a = 10 ;&#xA;a = &#34;Hello World !&#34;&#xA;//output : TypeError: Assignment to constant variable.&#xA;}ولی :function (){&#xA; let a = 10 ;&#xA; a = &#34;Hello World !&#34;&#xA;console.log(a)&#xA; //output : Hello World !&#xA;}آقا داودامیدوارم مفید باشه :)</description><category>Davood Habbabi</category><author>Davood Habbabi</author><pubDate>Tue, 26 Jan 2021 13:10:15 +0330</pubDate></item><item><title>مفهوم Hoisting در جاوا اسکریپت</title><link>https://virgool.ir/Gajino-FrontEnd/مفهوم-hoisting-در-جاوا-اسکریپت-svf3tjp91jwb</link><description>دوستان سلاماین Hoisting قصه ما خیلی اسمش بزرگه ولی خودش هیچی نیست بریم ببینیم چی هس اصلا این کد ها رو در نظر بگیرید console.log(a);&#xA;// output : ReferenceError : a is not definedو این قطعه کد رو :var a;&#xA;console.log(a);&#xA;//output : undefinedفرق این ارور ها چیه ؟اولیش a کلا وجود نداره و کلا ReferenceError می ده و توضیح می ده که متغیر یا ثابتی به اسم a وجود نداره ولی توی مورد دوم a وجود داره ولی مقدارش undefined یعنی مقدار دهی نشده برنامه ارور نمی ده و توی کنسول مقدار undefined چاپ می شه خب حالا Hoisting چیه ؟باز می خوام مثال بزنم این تیکه کد رو در نظر بگیرید :console.log(a);&#xA;var a = 40;&#xA;// output : undefined اگر کد های جاوا اسکریپت دقیقا خط به خط کامپایل و اجرا بشن توقع داریم مثل مورد اول با ReferenceError  مواجه بشیم و کد اجرا نشه و به ارور بخوره ولی نمی خوره :) و مقدار برابر با undefined می شه چرا ؟می دونیم که کد های جاوا اسکریپت یک بار کامپایل و سپس اجرا می شن تعریف متغییر ها حین کامپایل اتفاق می افته و مقدار دهی به متغییر ها حین اجرا یعنی چی ؟یعنی کامپیوتر کد های بالا رو به این صورت می بینیه var a;&#xA;console.log(a);&#xA;a = 40;بخاطر همینه که ارور نمی ده و مقدار undefined می شه معنی Hoisting یعنی بالا کشیدن اگر دقت کنید تعریف متغییر ها به بالای برنامه کشیده شد آقا داود امیدوارم مفید باشه :)</description><category>Davood Habbabi</category><author>Davood Habbabi</author><pubDate>Sun, 24 Jan 2021 17:39:01 +0330</pubDate></item><item><title>ویژگی onError در تگ img</title><link>https://virgool.ir/Gajino-FrontEnd/ویژگی-onerror-در-تگ-img-me2pascz5zxv</link><description>لود نشدن عکس ها جز فجایعی هستش که توی سایت ها باهاش به رو به رو می شیم اگر هندلش نکنیم وبسایتمون رو از ریخت می اندازهولی خب همچین بی راه حل نیست و می شه این مشکل رو به نوعی کنترل کرد قطعا همچین تصویری رو توی همه سایت ها دیدین به این تصاویر می گن placeholder در واقع این نوع تصاویر جای خالی تصویر اصلی رو پر کرده (ممکنه تصویر لود نشده باشه یا توی لود به ارور خورده باشه)یه ویژگی عکس ها دارن به اسم  این ویژگی کمک می کنه تا ما بفهمیم لود شدن عکس به هر دلیلی ارور خورده و می تونیم از نمایش تصویر شکسته در سایت جلوگیری کنیم این تیکه کد ساده رو ببینید &lt;!DOCTYPE html&gt;&#xA;&lt;html&gt;&#xA;  &lt;body&gt;&#xA;    &lt;img src=&#34;image.gif&#34; =&#39;myFunction()&#39;&gt;&#xA;    &#xA;      function myFunction() {&#xA;        alert(&#39;The image could not be loaded.&#39;);&#xA;      }&#xA;&#xA;  &lt;/body&gt;&#xA;&lt;/html&gt;نتیجه این تیکه کد :هر وقت لود عکس به ارور بخوره یه آلرت با متن &#34;The image could not be loaded&#34; به کاربر نمایش داده می شه با همین منطق می تونیم src رو عوض کنیم یا عکس رو حذف کنیم یا هر بلایی سر صفحه بیاریم :)اینم لینک رفرنسMDNw3schoolsامیدوارم مفید باشه</description><category>Davood Habbabi</category><author>Davood Habbabi</author><pubDate>Sat, 23 Jan 2021 13:57:27 +0330</pubDate></item><item><title>بهترین منبع یادگیری جاوااسکریپت</title><link>https://virgool.ir/Gajino-FrontEnd/بهترین-منبع-یادگیری-جاوااسکریپت-nqoxcqnvjxyi</link><description>یه سوالی که اغلب پرسیده می شه و کسی که یکم تو جاوا اسکریپت مهارت داشته باشه در واقع هیچ جوابی براش نداره می پرسی چرا ؟ می گم براتبرای هیچ زبانی اغلبا منبع محکمی نیست بخوای بخونی و دیگه توش قوی باشی چون زبان ها در حال آپدیت هستند و شما باید از هر منبعی برای بروز موندن اطلاعاتت استفاده کنیفقط 30 درصد از برنامه نویسی تئوری هستش و بقیش رو تجربه و سرچ خوب می سازه خیلی از موارد تئوری انقدر عمیقه که اغلبا توی کتاب های جامع بهش نمی رسید پس چی کار باید کرد ؟چطوری باید به سطح مطلوب رسید راهکار من به شما اینه که اصلا مهم نیست با چه منبعی پیش می ری (کامل یا ناقص)مهم اینه که شروع کنی و پیش بری اغلبا مطالعه کردن توی هر زمینه ای کنجکاوی هایی رو پیش میاره این کنجکاوی ها رو باید یادداشت کنید در این صورت دو تا حالت وجود داره یا همون منبعی که می خونید جواب شما رو 4 قدم جلوتر می ده یا این که از قلم انداخته و شما باید جای دیگه دنبالش بگردین دیده شده این نوع سوال ها باعث شده فردی ماه ها درگیر منبع خوب برای مطالعه هستش یا رفرنس خاصی می خواد برای یادگیری در آخر منابعی که می تونید باهاش جاوااسکریپت رو مطالعه کنید w3schools.com (website)javascript.info (website)eloquentjavascript.net (website and book)developer.mozilla.org (website)you don&#39;t know js (book series)امیدوارم مفید باشه </description><category>Davood Habbabi</category><author>Davood Habbabi</author><pubDate>Sat, 26 Dec 2020 13:42:16 +0330</pubDate></item><item><title>مشکل نصب eslint</title><link>https://virgool.ir/WebDevelopers/مشکل-نصب-eslint-و-ارور-the-react-scripts-package-provided-by-create-react-app-requires-a-dependency-jploggpn0ku4</link><description>خب ظاهر این ارور این شکلیه در واقع داره توضیح می ده که به صورت دستی eslint  رو تغییر ندید و node modules  رو پاک کنید و روندی که هیچ کمکی به حل مشکل نمی کنه و در واقع این یه پیشنهاد عمومی برای رفع مشکلاته کلی گشتم یه جوابی پیدا کردم که نمی دونم چه تاثیراتی روی پروژه می ذاره ولی کار کردروند اینه توی پروژه فایل env. رو پیدا کنید و اگر نیست ایجاد کنید این خط رو بهش اضافه کنید SKIP_PREFLIGHT_CHECK=trueسیو کنید npm start  رو متوقف و از نو npm start بزنید :)لطفا اگر کسی اطلاع داره این چه تاثیری روی پروژه می ذاره بهم توی کامنت ها بگید </description><category>Davood Habbabi</category><author>Davood Habbabi</author><pubDate>Sat, 21 Nov 2020 15:08:39 +0330</pubDate></item><item><title>ساختن بردر خاص با Css</title><link>https://virgool.ir/@i_am_davood/ساختن-بردر-خاص-با-css-qbwtccelquai</link><description>دوستان دیشب توی یک گروه تلگرامی داشتم مشکلات دیگران رو می خوندم تا رسیدم به یک سوال باحال سوال این بود : چطور می شه این بردر رو با Css ایجاد کرد ؟سوالش برام جذاب بود پس سعی کردم این باکس خوشگل رو بسازمخب باید بگم که خود Css کد خاصی نداره که بتونه همچین بردری ایجاد کنه و ما در واقع با ترکیب اشکال ساده تر (مثل دایره ، مربع ، مستطیل ) می تونیم این باکس ها رو ایجاد کنیم خب برای شروع کد HTML زیر رو به عنوان مثال در نظر بگیرید&lt;!DOCTYPE html&gt;&#xA;&lt;html&gt;&#xA;   &lt;body&gt;&#xA;       &lt;div id=&#34;demo&#34;&gt;&#xA;       &lt;/div&gt;&#xA;   &lt;/body&gt;&#xA;&lt;/html&gt;خب برای شروع باکس demo رو یه ابعاد خیالی بهش می دیم مثلا 400 در 300 پیکسل و بعد بهش یک بردر با ضخامت 5 پیکسل و استایل های دیگه که در نهایت به شکل زیر درمیاد#demo {&#xA;    width: 400px;&#xA;    height: 300px;&#xA;    border: 5px solid #b32fd4;&#xA;    box-sizing: border-box;&#xA;    position: relative;&#xA;}خب باکسمون به این شکل درمیاد خب حالا باید به این باکس دو تا یک چهارم دایره به دو تا گوشه بالایی باکس اضافه کنیممی دونیم که توی Css  دو نیم المنت after و before وجود دارن از این دو تا بزرگوار کمک می گیریم برای ساختن دو تا یک چهارم دایره ولی چطوری ؟کاری نداره کافیه یک باکس با طول و عرض یکسان (مثلا 100 × 100 ) بسازیم و border-radus با همون مقدار (100 پیکسل ) بهش بدیم اینجوری دایره ساخته می شه حالا از 4 طرف بهش بردر می دیم و یک طرف رو برای بردر رنگ مشخص و 3 طرف دیگه رو مقدار رنگ بردر رو transparent می دیم یعنی اینجوری     content: &#34;&#34;&#xA;    display: block;&#xA;    width: 100px;&#xA;    height: 100px;&#xA;    border-left: 5px solid #b32fd4;&#xA;    border-top: 5px solid transparent;&#xA;    border-bottom: 5px solid transparent;&#xA;    border-radius: 100px;خب الان فقط کافیه سمتی که می خوایم بچرخونیمش و جایی که دوست داریم تنظیمش کنیم یعنی اینجوری#demo:after{&#xA;    content: &#34;&#34;&#xA;    display: block;&#xA;    width: 100px;&#xA;    height: 100px;&#xA;    border-radius: 100px;&#xA;    background: white;&#xA;    box-sizing: border-box;&#xA;    border-right: 5px solid #b32fd4;&#xA;    border-top: 5px solid transparent;&#xA;    border-bottom: 5px solid transparent;&#xA;    transform: rotate(45deg);&#xA;    position: absolute;&#xA;    top: -55px;&#xA;    left: -55px;&#xA;}#demo:before{&#xA;    content: &#34;&#34;&#xA;    display: block;&#xA;    width: 100px;&#xA;    height: 100px;&#xA;    border-left: 5px solid #b32fd4;&#xA;    border-top: 5px solid #b32fd400;&#xA;    border-bottom: 5px solid #b32fd400;&#xA;    border-radius: 100px;&#xA;    background: white;&#xA;    box-sizing: border-box;&#xA;    transform: rotate(-45deg);&#xA;    position: absolute;&#xA;    top: -55px;&#xA;    right: -55px;&#xA;}نتیجه نهایی این کد ها می شه این تصویربدون درد و خون ریزی تونستیم از این باکس خوشگلا درست کنیم :)</description><category>Davood Habbabi</category><author>Davood Habbabi</author><pubDate>Wed, 15 Apr 2020 18:55:45 +0430</pubDate></item><item><title>رفع مشکل صفحه سیاه در vsCode</title><link>https://virgool.ir/Gajino-FrontEnd/رفع-مشکل-صفحه-سیاه-در-vscode-aqekeim3szld</link><description>سلام دوستان امروز به یه مشکلی خورم که بعد یکم سرچ و اینا به جوابش رسیدم مشکل آنچنان حاد و خطرناکی نیست ولی خب وقتمو گرفت تا حل بشه بعد از نصب vsCode صفحه کاملا مشکی شد و هر کاری کردم درست نشد (برای مهندس کامپیوتر عموما هر کاری کردم یعنی کامپیوتر رو ریستارت کردم )در واقع چیزی که می دیدم این بودیکم که سرچ زدم این لینکو پیدا کردم :https://github.com/Microsoft/vscode/issues/51701توش نوشته بود برای باز کردنش از این کامند توی ترمینال یا cmd استفاده کنید code --disable-gpuنوشته های دیگر من : رفع ارور esLint , بهترین منبع یادگیری جاوااسکریپت , ویژگی  در imgخب این به درد من نمی خورد چون با هر بار برای بازکردن vscode باید از cmd شروع می کردم (دوس دارم با کلیک باز شه ) تازه وقتی با این روش بازش می کردم دیگه ترمینال خود vscode کار نمی کرد بازم سرچ زدم و رسیدم به این لینکhttps://stackoverflow.com/questions/29966747/how-can-i-disable-gpu-rendering-in-visual-studio-codeکه خب مشکلم رو حل کرد جالبه بدونید اون جوابی مشکلمو حل کرد که تیک نخورده بود (پس تو استک اورفلو جواب هایی که تیک نخورده رو هم نگاه بندازید حتما) راه حلی که ارائه شده بود این بود و خب مشکلم رو حل کرد :با روش بالا vsCode رو باز کنید کلید های Ctrl + Shift + P رو بفشاریداون بالا تایپ کنید Preferences: Configure Runtime Arguments (پس از انتخاب یک فایل براتون باز می شه)بعد از باز شدن فایل دستور &#34;disable-hardware-acceleration&#34;: true رو به انتهای فایل اضافه کنید خب vscode  رو ببندید و دوباره باز کنید :)</description><category>Davood Habbabi</category><author>Davood Habbabi</author><pubDate>Tue, 14 Apr 2020 16:39:52 +0430</pubDate></item><item><title>چطوری در صفحه HTML یه مثلث بسازیم ؟</title><link>https://virgool.ir/@i_am_davood/چطوری-در-صفحه-html-یه-مثلث-بسازیم-fwbvu6ihspch</link><description>سلام همیشه مشکل ساخت مثلث رو در Html داشتیم و چون تگ خاصی در html یا پراپرتی واضحی برای ساخت مثلث ها نبوده گیج می شدیم!خب اینجا میخوام ساخت مثلث بدون درد و خونریزی رو به شما یاد بدم ( وای چقدر بانمکم من ) راه اول (تگ img)استفاده از ایکون های موجود و آپلود کردن کردن اون ها و استفاده شون داخل تگ img هستشاین روش مزیتش سادگی اون در استفاده هستش و برای کسایی که دانش کافی ندارن بهترین روشهولی خب از معایبش می شه به غیر قابل ادیت بودن با کد اشاره کرد یعنی اگر شما نیاز داشته باشی مثلث با hover  شدن رنگش تغییر کنه دردسر های زیادی رو باید تحمل کنی راه دوم (استفاده از svg )خب می شه گفت svg اصلا مشکلات تگ img رو نداره یعنی یه تعدادی از خواص این تگ مثل رنگ قابل ادیته  ولی اگر لازم باشه بجای مثلث متساوی الضلاع یه مثلث متساوی الساقین داشته باشیم چی ؟باید بگم استفاده و کار آمدی زیادی داره ولی یکی از معایبش اینه که اگر قرار باشه نسبت اضلاع رو تغییر بدیم نیاز داریم با ادیتور های عکس مثل photoshop عکس رو تغییر بدیم و تغییر کد های svg واقعا کار سختیه راه سوم ( استفاده از فونت ایکون ها مثل font awesome )خب این روش هم همچنان مثل svg  هستش با این تفاوت که از قبل طراحی شدن و شما فقط باید نصبش کنید و به پروژه اضافشون کنید ولی یه مثلث ساده نباید این همه دردسرتون بده مگه نه ؟راه چهارم ( Css Border )خب خب این راه یه جورایی جز فنون آخر استاد در css حساب می شه و از یه باگ یه قابلیت در آوردنه یعنی چی ؟ببینید فرض کنید یه باکسی داریم با مشخصات زیر :به عنوان نتیجه خواهی داشت (بردر ها رو با رنگ های متفاوت انتخاب کردم تا از طریق رنگ بردر های بالا و چپ و راست و پایین به راحتی مشخص باشه و قابل تفکیک ) :حالا می خوام طول و عرض (width &amp; height) باکس رو برابر صفر قرار بدم به عنوان نتیجه خواهیم داشت :حالا کافیه از 3 جهت دلخواه رنگ border و background-color رو برابر transparent  قرار بدید مثلا :به عنوان نتیجه خواهیم داشت :روش خوشمزه ای برای ساختن مثلثه مخصوصا واسه اونایی که مثل من سرشون درد می کنه از روش های غیر متعارف به هدفشون برسن :)))خب حالا فرض کنید بخوام یه دکمه داخل این مثلث هایی که با 4 روش بالا ساختیم بذاریم (یکی نیست بهم بگه چی از جون این مثلث بدبخت می خوای ) خب عملا با 4 روش بالا غیر ممکنه که داخلشون المنت دیگه ای گنجوند ولی یه راه پنجمی هم هست :))))راه پنجم (Css Clip Path)از طریق این قابلیت باحال Css می شه اشکال خیلی زیادی رو ساخت و من قصد ندارم دقیقا منطق کارش رو به شما توضیح بدم (برید مطالعه کنید خب به من چه ) فقط قصد دارم بهتون بگم که از طریق این قابلیت می شه یه div ساده رو تبدیل به مثلثی کرد که می شه توش هر المنت HTML دیگه ای تعریف کردبرای ساختن اشکال مختلف از طریق Clip Path یه سایتی هست که خیلی راحت می تونید باهاش هرچی می خواید بسازید و اصلا نخونید چطوری کار می کنه (مدیونید اگر فکر کنید خودم ازش استفاده می کنم ) ادرس سایت هم اینه :  https://bennettfeely.com/clippy/الان که من دارم این مطلب رو می نویسم باید از خاک‌برسر شکن استفاده کنید تا باز بشه نمی دونم از طرف ما یا اونا بستس ولی می دونم که بستساز معایب این روش ساختن اشکال اینه که به صورت دیفالت خاصیت overflow برابر با مقدارhidden هستش یعنی اگر شما المنتی دارید که به هر دلیلی بخشیش یا کلش بیرون شکلتون باشه نمایش داده نخواهد شد (حتی شما دوست عزیز ) راه حلی هم نداره مگر با روش های غیر متعارف دیگه شکلتون رو بسازید </description><category>Davood Habbabi</category><author>Davood Habbabi</author><pubDate>Thu, 09 Apr 2020 00:54:59 +0430</pubDate></item></channel></rss>