<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
    <channel>
        <title>نوشته های فرزاد یوسف زاده</title>
        <link>https://virgool.io/feed/@farskid</link>
        <description>مهندس نرم افزار. با کمی فعالیت در pullrequest.ir</description>
        <language>fa</language>
        <pubDate>2026-06-17 10:59:05</pubDate>
        <image>
            <url>https://files.virgool.io/upload/users/1281/avatar/qnjdWu.png?height=120&amp;width=120</url>
            <title>فرزاد یوسف زاده</title>
            <link>https://virgool.io/@farskid</link>
        </image>

                    <item>
                <title>پنهان کردن هدرهای پیش فرض مرورگر در پرینت صفحه وب</title>
                <link>https://virgool.io/pullrequest/%D9%BE%D9%86%D9%87%D8%A7%D9%86-%DA%A9%D8%B1%D8%AF%D9%86-%D9%87%D8%AF%D8%B1%D9%87%D8%A7%DB%8C-%D9%BE%DB%8C%D8%B4-%D9%81%D8%B1%D8%B6-%D9%85%D8%B1%D9%88%D8%B1%DA%AF%D8%B1-%D8%AF%D8%B1-%D9%BE%D8%B1%DB%8C%D9%86%D8%AA-%D8%B5%D9%81%D8%AD%D9%87-%D9%88%D8%A8-spfatjzfpqz0</link>
                <description>ممکنه نیاز داشته باشید صفحه وب رو با جاوااسرکیپت پرینت کنید. خود این تسک کار ساده ایه و با یه دستوری ساده مثل window.print() انجام پذیره. اما یه مشکلی توی این پرینت وجود داره و اونم اینه که تنظیمات پیش فرض مرورگرها عنوان صفحه و تاریخ روز رو بالای صفحه ای که میخواید پرینت بگیرید وارد میکنه، مثل عکس زیر:اگر بخوایم اونو پنهان کنیم کافیه دستور زیر رو توی فایل سی اس اس پروژه قرار بدید تا از شر اون هدر خلاص بشید:@media print {
  @page {
    size: auto;
    margin: 0mm;
  }
}یادتون نرهاون قسمت @media print رو از قلم نندازید. این کد توی سی اس اس اصلی ممکنه عوارض جانبی توی مرورگرهای قدیمی تر به بار بیاره و بهتره فقط توی حالت پرینت اعمال بشه.برای اطلاعات بیشتر در مورد سلکتور @page میتونین به لینک زیر مراجعه کنید.MDN @page guide</description>
                <category>فرزاد یوسف زاده</category>
                <author>فرزاد یوسف زاده</author>
                <pubDate>Sun, 16 Jul 2017 15:17:27 +0430</pubDate>
            </item>
                    <item>
                <title>ساخت کلاس Singleton در جاوااسکریپت ES6</title>
                <link>https://virgool.io/pullrequest/%D8%B3%D8%A7%D8%AE%D8%AA-%DA%A9%D9%84%D8%A7%D8%B3-singleton-%D8%AF%D8%B1-%D8%AC%D8%A7%D9%88%D8%A7%D8%A7%D8%B3%DA%A9%D8%B1%DB%8C%D9%BE%D8%AA-es6-n2l5nol1e2cd</link>
                <description>ساختن کلاس و استفاده ازش در جاوااسکریپت که به صورت ذاتی یک زبون Object Oriented نیست، همیشه برای توسعه دهنده ها کار چالش برانگیزی بوده. با معرفی شدن استاندارد ES6 در سال ۲۰۱۵، بخش عظیمی از این چالش ها و تمامی ترفندهایی که برای شبیه سازی کلاس ها در جاوااسکریپت استفاده می شد،‌ دیگه کاربردشون رو از دست دادن. درحال حاضر اکثر توسعه دهندگان جاوااسکریپت از استاندارد ES6 استفاده میکنن و دیگه ساختن و استفاده از کلاس کار نسبتا ساده ای شده.به عنوان نمونه یه کلاس Student در جی اس مدرن، به سادگی زیر ساخته و استفاده میشه:// Define
class Student {
  constructor(name) {
    this.name = name
  }

  whoAmI() {
    return `I am ${this.name}`
  }
}

// Use
const todd = new Student(&#039;Todd&#039;)
todd.whoAmI() // Returns: `I am Todd`کلاس Singletonاگر نیاز باشه کلاسی که تعریف میکنید، فقط یه اینستنس ازش وجود داشته باشه و هربار new گرفتن ازش،‌همون اینستنش رو برگردونه، به این کلاس میگن کلاس Singleton. نمونه هایی که میشه از Singleton استفاده کرد:سرویس لاگرسرویس ذخیره سازی و خواندن از یک پوشه در فایل سیستمسرویس خواندن از کانفیگ پروژه…استفاده از Singleton همیشه باید ۳ مورد زیر رو پوشش بده. اگر Singleton ای که دارید میسازید هر ۳ مورد رو پوشش نمیده مطمئن باشید دارید جایی از کار رو اشتباه میزنید :دیکنترل کردن ارتباطات کانکارنت روی یه ریسورسکنترل ارتباط به یه ریسورس از مکان ها و سرویس های مختلف و ایزوله از همتنها یه آبجکت از کلاس خارج بشهساخت Singleton در ES6برای ساخت یه سینگلتون میتونید از کدبیس زیر الهام بگیرید:// SingletonService.js

let instance = null

class SingletonService {
  constructor() {
    if (!instance) {
      instance = this
    }

    return instance
  }

  // All other stuff here

}</description>
                <category>فرزاد یوسف زاده</category>
                <author>فرزاد یوسف زاده</author>
                <pubDate>Sat, 08 Jul 2017 14:59:41 +0430</pubDate>
            </item>
                    <item>
                <title>فرار از جهنم Callback با تبدیل Callback به Promise</title>
                <link>https://virgool.io/pullrequest/%D9%81%D8%B1%D8%A7%D8%B1-%D8%A7%D8%B2-%D8%AC%D9%87%D9%86%D9%85-callback-%D8%A8%D8%A7-%D8%AA%D8%A8%D8%AF%DB%8C%D9%84-callback-%D8%A8%D9%87-promise-cvyvvjgorlf8</link>
                <description>جهنم callbackبرای کار با توابع Asynchronous در جاوااسکریپت، از کالبک (Callback) استفاده میشه. با اینکه این راه در خیلی از موارد ممکنه مشکل رو حل کنه، زمانی که به انجام چند عمل Async باهم و در ادامه هم میرسیم، استفاده از Callback ما رو درگیر مشکلی به اسم جهنم Callback یا ٖ Callback Hell میکنه. برای حل این مشکل خوبه که بدونیم میشه Callback ها رو تبدیل به Promise کرد.نوشتن تبدیلبرای اینکه بدونیم چطور میشه Callback رو به Promise تبدیل کرد، باید بدونیم Promise چه خصوصیاتی داره. نمیخوام وارد جزییات تعریفش بشم. اگر نمیدونین Promise چیه میتونین به تعریف پرامیس مراجعه کنین.برای سادگی نشون دادن این تبدیل بیایم یه عمل Async ساده رو درنظر بگیریم و باهم از حالت کالبک، به پرامیس تبدیلش کنیم.برای مثال در استفاده از فایل سیستم در Nodejs، تابعی وجود داره به اسم fs.readFile که خیلی ساده میتونین با استفاده ازش، محتویات یه فایل در فایل سیستم رو بخونید. متناظر با این تابع، fs.writeFile هم وجود داره که میتونید با استفاده ازش یه محتوایی رو توی یه فایل ذخیره کنید.فرض کنید دو فایل داریم توی فولدر files پروژه با نام های:read.txtwrite.txtو میخوایم محتویات فایل read.txt رو بخونیم و توی فایل write.txt ذخیره کنیم. به صورت پیش فرض در Nodejs اکثر عملیات ها Async هستن (این برمیگرده به ذات None-blocking-IO) و پارامتری رو به عنوان کالبک دریافت میکنن. کد زیر رو ببینید:// Basic variables
const filesBaseDir = __dirname + &#039;/files&#039;
const filesDir = {
  read: filesBaseDir + &#039;/read.txt&#039;,
  write: filesBaseDir + &#039;/write.txt&#039;
}
const fs = require(&#039;fs&#039;)

// Utils
const readFile = (fileDir, success, fail) =&gt; {
  fs.readFile(fileDir, (err, data) =&gt; {
    if (err) return fail(err)
 
    return success(data)
  })
}
const writeFile = (fileDir, content, success, fail) =&gt; {
  fs.writeFile(fileDir, content, (err) =&gt; {
    if (err) return fail(err)

    return success()
  })
}حالا با درنظر داشتن کد بالا عملیات مدنظر رو انجام میدیم:readFile(filesDir.read, (data) =&gt; {
  // Now write data to write.txt
  writeFile(filesDir.write, data, () =&gt; {
    console.log(&#039;Mission accomplished!&#039;)
  }, (err) =&gt; {
    console.error(&#039;Error writing to file...)
  })
}, (err) =&gt; {
  console.error(&#039;Error reading file...&#039;)
})qخب به خوبی و خوشی تونستیم دو تابع Async رو باهم ادغام کنیم و زنجیره وار ازشون استفاده کنیم. تا همینجاش وقتی حتی فقط 2 تابع Async وجود داشت، دردسر زیادی برای ادغامشون کشیدیم، حالا اگر قرار بود ۴تا یا حتی ۱۰تا عمل Async رو پشت هم و در ادامه هم انجام میدادیم چطور؟ ۱۰ عمل Async در ادامه هم یعنی فراخوانی 9 کالبک در کالبک قبلی!! اسم دیگه ای به جز جهنم نمیشه براش گذاشت!برای رهایی ازین شرایط کافیه بدونیم میتونیم توابع Async ای که کالبک میپذیرن رو به Promise تبدیل کنیم. ممکنه در وهله اول این تبدیل ارزش چندانی براتون نداشته باشه، اما اجازه بدین نشونتون بدم چطور زندگی براتون ساده تر میشه وقتی از جهنم میاین بیرون :))نوشتن دوباره با استفاده از Promise هاهمون فانکشن های قبلی رو اینبار با استفاده از پرامیس مینویسیم:// Convert Callbacks to Promisified version
const promisifiedReadFile = (fileDir) =&gt; {
  return new Promise((resolve, reject) =&gt; {
    readFile(fileDir, (data) =&gt; resolve(data), (e) =&gt; reject(e))
  })
}
const promisifiedWriteFile = (fileDir, data) =&gt; {
  return new Promise((resolve, reject) =&gt; {
    writeFile(fileDir, data, () =&gt; resolve(), (e) =&gt; reject(e))
  })
}حالا از ورژن Promisified استفاده میکنیم:promisifiedReadFile(filesDir.read)
  .then((data) =&gt; promisifiedWriteFile(filesDir.write, data))
  .then(() =&gt; {
    console.log(&#039;Mission accomplished!&#039;)
  })
  .catch(e =&gt; console.error(&#039;Error&#039;))خاصیت پرامیس ها اینه که به تعداد نامحدود هم اگر باشن میشه به راحتی در قالب .then های پشت هم ازشون استفاده کرد. پرامیس مثل بلاک try-catch عمل میکنه، به این معنی که نیازی نیس برای هر .then یه .catch قرار بدیم درحالیکه کافیه Exception رو در هر جایی از این زنجیره return کنیم و فقط یه .catch در انتهای زنجیره قرار بدیم تا بتونه این Exception رو بگیره.اگر هم براتون واقعا مهمه :پوکرفیس که بدونین کجای پروسه به مشکل خوردین، منظورم نوع اروریه که توی پروسه اتفاق میوفته، کافیه نوع ارور خاص خودتون رو بسازید تا با استفاده از اون بتونید نوع مشکل پیش اومده رو پیش بینی کنید:class ReadError extends Error {}
class WriteError extends Error {}و در نهایت توی توابع مربوطه ارور مناسبش رو return کنین تا توسط catch انتهای زنجیره گرفته بشه.const readFile = (fileDir, success, fail) =&gt; {
  fs.readFile(fileDir, (err, data) =&gt; {
    if (err) return new ReadError(err)
 
    return success(data)
  })
}
const writeFile = (fileDir, content, success, fail) =&gt; {
  fs.writeFile(fileDir, content, (err) =&gt; {
    if (err) return new WriteError(err)

    return success()
  })
}در نهایت اینکه (Rule of Thumb)برای تبدیل هر کالبک به پرامیس کافیه یه تابع ساخته بشه که یه پروامیس برگردونه. هم چنین این پرامیس دو تابع resolve و reject به عنوتن پارامتر دریافت کنه. توی بدنه این تابع، اون تابع کالبک دار اولیه رو فراخونی کنین و موقعی که ارور ندارید، resolve رو صدا کنین و موقعی که به ارور میخوره reject کنین. همین!مطمئن باشید زندگی با Promise خیلی ساده تر از کالبکه به خصوص زمانی که بخواین زنجیری از کالبک ها رو صدا کنید!هم چنین اگر از Nodejs استفاده میکنین پیشنهاد میکنم از پکیج es6-promisifyاستفاده کنید و توابع Callback دار نود جی اس رو به پرامیس تبدیل کنید.خوشحال میشم ایده هاتون رو در مورد این مطلب توی کامنت ها ببینم تا فیبدک هامون رو به هم منتقل کنیم.اگر از خوندن این مطلب لذت بردین میتونین اونو با دیگران به اشتراک بزارید. همینطور میتونین از سایر مطالب بلاگ هم استفاده کنین و یا اگر دوس داشته باشید، کنارمون بنویسید. برای راهنمای انتشار مطلب در پول ریکوئست میتونین با ما در تماس باشید.</description>
                <category>فرزاد یوسف زاده</category>
                <author>فرزاد یوسف زاده</author>
                <pubDate>Thu, 27 Apr 2017 14:17:02 +0430</pubDate>
            </item>
                    <item>
                <title>هماهنگ سازی مخزن Fork شده با مخزن اصلی</title>
                <link>https://virgool.io/pullrequest/%D9%87%D9%85%D8%A7%D9%87%D9%86%DA%AF-%D8%B3%D8%A7%D8%B2%DB%8C-%D9%85%D8%AE%D8%B2%D9%86-fork-%D8%B4%D8%AF%D9%87-%D8%A8%D8%A7-%D9%85%D8%AE%D8%B2%D9%86-%D8%A7%D8%B5%D9%84%DB%8C-yr52g7vv5fkw</link>
                <description>هر زمان که بخواین یه مخزن رو توی گیتهاب برای خودتون ذخیره کنین یا بخواین بهش یه Contribution داشته باشید، باید در مرحله اول اون مخزن رو Fork کنین. ولی اگر صاحب مخزن اصلی اونو آپدیت کنه چی؟ چطور باید مخزن Fork شده تون رو باهاش هماهنگ و آپدیت نگه دارین؟(مخزن = Repository)نحوه هماهنگ سازی دو مخزن ها باهمبرای آپدیت و هماهنگ نگه داشتن مخزن لوکال تون با مخزن اصلی باید دو مرحله رو پشت سر بزارین:مرحله اول: اضافه کردن ریموت Upstreamتو این مرحله یه ریموت به مخزن اصلی ست میکنیم. خط فرمان رو باز کنین و برید توی فولدر مخزنی که فورکش کردین: حالا دستور git remote -v رو وارد کنین تا لیست ریموت های ست شده روی فورکتون مشخص بشه:$ git remote -v
origin  https://github.com/YOUR_USERNAME/YOUR_FORK.git (fetch)
origin  https://github.com/YOUR_USERNAME/YOUR_FORK.git (push)میبینین که یه ریموت به فورکتون توی مخزن ست شده. حالا باید یه ریموت دیگه به مخزن اصلی اولیه ست کنیم:git remote add upstream https://github.com/ORIGINAL_OWNER/ORIGINAL_REPOSITORY.gitبه این ریموت Upstream میگن. برای اینکه مطمئن بشین ریموت Upstream به مخزنتون اضافه شده دوباره دستور git remote -v رو توی خط فرمان اجرا کنین:$ git remote -v
origin    https://github.com/YOUR_USERNAME/YOUR_FORK.git (fetch)
origin    https://github.com/YOUR_USERNAME/YOUR_FORK.git (push)
upstream  https://github.com/ORIGINAL_OWNER/ORIGINAL_REPOSITORY.git (fetch)
upstream  https://github.com/ORIGINAL_OWNER/ORIGINAL_REPOSITORY.git (push)مرحله دوم: انجام آپدیت و هماهنگ سازی دو مخزنتوی همون خط فرمان، این دستور رو وارد کنین تا آخرین تغییرات مخزن اصلی به مخزن لوکالتون اضافه بشه:$ git fetch upstream
remote: Counting objects: 75, done.
remote: Compressing objects: 100% (53/53), done.
remote: Total 62 (delta 27), reused 44 (delta 9)
Unpacking objects: 100% (62/62), done.
From https://github.com/ORIGINAL_OWNER/ORIGINAL_REPOSITORY
 * [new branch]      master     -&gt; upstream/masterدر این لحظه آخرین تغییرات رو وارد سیستمتون کردین. برای اضافه شدنش به مخزن این دستورها رو اجرا کنین:$ git checkout master
Switched to branch &#039;master&#039;حالا برنچ فعلی رو مرج کنین با Upstream$ git merge upstream/master
Updating a422352..5fdff0f
Fast-forward
 README                    |    9 -------
 README.md                 |    7 ++++++
 2 files changed, 7 insertions(+), 9 deletions(-)
 delete mode 100644 README
 create mode 100644 README.mdتوی این حالت اگر تغییری وجود نداشته باشه،‌ گیت fast-forward اجرا میکنه:$ git merge upstream/master
Updating 34e91da..16c56ad
Fast-forward
 README.md                 |    5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)خوشحال میشم ایده هاتون رو در مورد این مطلب توی کامنت ها ببینم تا فیبدک هامون رو به هم منتقل کنیم.اگر از خوندن این مطلب لذت بردین میتونین اونو با دیگران به اشتراک بزارید. همینطور میتونین از سایر مطالب بلاگ هم استفاده کنین و یا اگر دوس داشته باشید، کنارمون بنویسید. برای راهنمای انتشار مطلب در پول ریکوئست میتونین با ما درتماس باشید.</description>
                <category>فرزاد یوسف زاده</category>
                <author>فرزاد یوسف زاده</author>
                <pubDate>Sat, 15 Apr 2017 04:25:36 +0430</pubDate>
            </item>
                    <item>
                <title>متد کاربردی Object.select</title>
                <link>https://virgool.io/pullrequest/%D9%85%D8%AA%D8%AF-%DA%A9%D8%A7%D8%B1%D8%A8%D8%B1%D8%AF%DB%8C-objectselect-svgtavpspyuf</link>
                <description>همین چند لحظه پیش یکی از دوستانم در توییتر MValipour ایده ای رو باهام درمیون گذاشت مبنی بر اضافه کردن متدی به اسم Object.select که به نظرم خیلی کاربردی و جالب بود و تصمیم گرفتم تا تنور داغه تبدیلش کنم به یه مطلب توی بلاگ :pتوی نسخه ES۶ عبارت const به جاوااسکریپت اضافه شد. هم چنین پترنهایی برای انتخاب آیتم های مورد نیاز از آبجکت ها هم به جی اس اضافه شد به نام Destructing Pattern. توی این مطلب نمیخام واردش بشم و میتونین جستجوش کنین. خیلی کاربردیه بهتون قول میدم :)اما چیزی که توی این پترن وجود داره به صورت زیره: فرض کنین یه آبجکت داریم که هویت یه انسان رو نشون میده:const john = {
  name: &#039;john&#039;,
  lastName: &#039;Doe&#039;,
  age: 25
}الگوی Destructive توی ES6 بهمون اجازه میده در صورتی که مثلا فقط به اسم و سن این انسان نیاز داریم، فقط همونا رو ازش استخراج کنیم:const john = {
  name: &#039;john&#039;,
  lastName: &#039;Doe&#039;,
  age: 25
}

const {name, age} = john
// name == &#039;john&#039;, age == 25ولی این طرز استخراج آیتم های مورد نظر از یه آبجکت، زمانی که تعداد آیتم ها بالا میره و آبجکت بزرگ میشه خیلی خسته کننده و کثیف میشه. خوب میشد اگر متدی مثل Object.select وجود داشت که بهش آبجکتمون و آیتم هایی که ازش نیاز داریم رو پاس میدادیم و برامون همینکار رو انجام میداد:const john = {
  name: &#039;john&#039;,
  lastName: &#039;Doe&#039;,
  age: 25
}

Object.select = (obj, ...keys) =&gt; {
  const result = {}
  // If the key is an array, apply on all of it&#039;s items
  const apply = key =&gt; {
    key instanceof Array ?
      key.forEach(apply) :
      result[key] = obj[key]
  }

  apply(keys)
  return result
}

// before:
const {name, age} = john

// after:
Object.select(john, &#039;name&#039;, &#039;age&#039;)چرا از john.select استفاده نکنیم؟ممکنه سوال پیش بیاد چرا این متد رو به Object.prototype اضافه نکردیم تا راحت تر بتونیم از john.select(&#x27;name&#x27;, &#x27;age&#x27;) استفاده کنیم.درسته که در این صورت خیلی راحت تر میشه اما این به نظرم یه آنتی پترنه. یه گفته ی قدیمی هست که میگه:Don’t mess around with objects that aren&#x27;t yoursپکیج این متد در NPMمیتونین برای استفاده از این پکیج و متد در محیط Node از لینک زیر به مخزن رسمی اش در گیتهاب استفاده کنین:Object.Select Official repositoryخوشحال میشم ایده هاتون رو در مورد این متد توی کامنت ها ببینم تا فیبدک هامون رو به هم منتقل کنیم.اگر از خوندن این مطلب لذت بردین میتونین اونو با دیگران به اشتراک بزارید. همینطور میتونین از سایر مطالب بلاگ هم استفاده کنین و یا اگر دوس داشته باشید، کنارمون بنویسید. برای راهنمای انتشار مطلب در پول ریکوئست میتونین با ما درتماس باشید.</description>
                <category>فرزاد یوسف زاده</category>
                <author>فرزاد یوسف زاده</author>
                <pubDate>Sun, 09 Apr 2017 04:21:28 +0430</pubDate>
            </item>
                    <item>
                <title>پروکسی (Proxy) و کاربردهاش در جاوااسکریپت</title>
                <link>https://virgool.io/pullrequest/%D9%BE%D8%B1%D9%88%DA%A9%D8%B3%DB%8C-proxy-%D9%88-%DA%A9%D8%A7%D8%B1%D8%A8%D8%B1%D8%AF%D9%87%D8%A7%D8%B4-%D8%AF%D8%B1-%D8%AC%D8%A7%D9%88%D8%A7%D8%A7%D8%B3%DA%A9%D8%B1%DB%8C%D9%BE%D8%AA-dykqsirklj3k</link>
                <description>یکی از فیچرهایی که در نسخه ES6 به جاوااسکریپت اضافه شد، کانستراکتور Proxy هست.توی این مطلب باهم در مورد Proxy بیشتر یاد میگیریم وکاربردهایی که میتونه در برنامه نویسی روزانه جاوااسکریپتمون داشته باشه رو باهم بررسی میکنیم.نکته: نمونه کدها رو با ES6 نوشتم. برای استفاده ازش توی پروداکشن، حتما با ترنسپایلری مثل Babel تبدیلش کنید به ES5.پروکسی (Proxy) چیکار میکنه؟طبق تعریف MDN ، پراکسی بهمون اجازه میده یه آبجکت با اینترفیس خاصی که در ادامه توضیح میدم تعریف کنیم تا به کمکش بتونیم عملکردهای اساسی روی دیتا رو کنترل کنیم. به عبارتی دیگه، میتونیم پیدا کردن یه آیتم توی آبجکت، اضافه کردن آیتم جدید به آبجکت، حذف آیتم از آبجکت و … رو کنترل کنیم و براش یه Middleware بنویسیم.پروکسی (Proxy) چطور کار میکنه؟برای استفاده از Proxy، باید دو پارامتر بهش پاس داده بشه. پارامتر اول آبجکتی هست که میخوایم کنترلش کنیم. یادمون باشه در جاوااسکریپت، Function ها و آرایه ها هم آبجکت محسوب میشن و میشه به عنوان پارامتر اول به Proxy پاسشون داد.پارامتر دوم هندلری هست که طبق متدهاش، کنترلمون روی آبجکت رو پیاده سازی میکنیم.const proxy = new Proxy(obj, handler)هندلری که به عنوان پارامتر دوم پاس داده میشه متدهای زیادی رو قبول میکنه که لیست کاملش رو توی لینک MDN میتونید ببینید. دومورد از پرکاربردترین متدهای این هندلر (که توی این مطلب باهاشون کار میکنم)، Set و Get هستن.ست Set بهتون اجازه میده فرآیند اضافه شدن آیتم جدید به آبجکت مورد نظر رو کنترل کنید.گت Get بهتون اجازه میده فرآیند خوندن یه آیتم از آبجکت مورد نظر رو کنترل کنید.با Proxy چه کارایی میشه کرد؟اگر یادتون باشه یه متدی توی جاوااسکریپت به صورت آزمایشی اضافه شده بود به اسم Object.observe که الان دیگه از رده خارج شده و در اکثر موتورهای رندر جی اس حذف شده اس. کار این متد این بود که تغییرات روی یه آبجکت رو کنترل میکرد. کد زیر رو به عنوان مثال ببینید:var obj = {
  foo: 0,
  bar: 1
}
Object.observe(obj, function(changes) {
  console.log(changes);
})

obj.baz = 2
// [{name: &#039;baz&#039;, object: &lt;obj&gt;, type: &#039;add&#039;}]زمانی که تلاش میکردیم تا کلید baz رو به آبجکت obj اضافه کنیم، این فرآیند توسط Object.observe دیده میشد و یه لاگ نشون میداد از عملیاتی که انجام شده بود.[{name: &#039;baz&#039;, object: &lt;obj&gt;, type: &#039;add&#039;}]یکی از کارهایی که با Proxy میشه انجام داد Observe کردن آبجکت هاست تا بتونیم زمانی که آیتمی از آبجکت خونده میشه و یا بهش اضافه میشه، مطلعمون کنه.شبیه سازی Object.observe با استفاده از Proxyبرای مشاهده دائمی تغییرات یه آبجکت کافیه یه هندلر با متدهای Set و Get بسازیم و زمانی که عملیات های خوندن و اضافه کردن به آبجکت انجام میشه، اونو توی کنسول نشون بدیم:// The object we wanna control
let obj = {}

// Our handler to control object via Proxy
const handler = {
  get(obj, prop) {
    console.log(`Getting property ${prop} from object`)
    // Remember to so the default operation, returning the prop item inside obj
    return obj[prop]
  },
  set(obj, prop, value) {
    console.log(`Setting property ${prop} as ${value} in object`)

    // Do the default operation, set prop as value in obj
    obj[prop] = value

    /*
      Set method must return a value.
      Return `true` to indicate that assignment succeeded
      Return `false` (even a falsy value) to prevent assignment.in `strict mode`, returning false will throw TypeError
    */

    return true
  }
}

// Set the proxy
let proxifiedObj = new Proxy(obj, handler)

// Now to test the handler, Just set some stuff or read props from the obj
proxifiedObj.name = &#039;Farzad&#039; // Setting property name as Farzad in object
proxifiedObj.name // Getting property name from objectهمونطور که توی کد بالا مشخصه، یه هندلر ساختیم و برایش متدهای Set و Get نوشتیم. زمانی که یه آبجکت رو پراکسی میکنیم و یه آیتم ازش رو فراخوانی میکنیم مثل proxifiedObj.name، چون آبجکت proxifiedObj پراکسی شده، مستقیم مقدار .name خونده نمیشه، بلکه متد handler.getخونده میشه. که این متد یه لاگ به کنسول انجام میده و اعلام میکنه که چه آیتمی داره خونده میشه و بعدش مقدار این آیتم یعنی proxifiedObj.name رو ریترن میکنه.توی متد Set هم نوشتیم، زمانی که میخوایم آیتمی مثل name رو به آبجکتمون اضافه کنیم، به جای اینکه مستقیما این مقدار بهش اساین بشه، متد handler.set فراخوانی میشه. این متد هم لاگ میکنه که آیتم فلان با مقدار فلان قراره با آبجکتمون اضافه بشه.نکته: به کامنتی که در انتهای متد Set نوشتم دقت کنین. متد Set همیشه باید یه مقدار رو ریترن کنه. MDN توی توضیحاتش میگه این مقدار باید ترحیجا Boolean باشه اما در مثال های دیگه میبینیم که فقط کافیه این مقدار Falsy نباشه. امن ترین راه برای حفظ رفتار پیش فرض و اضافه کردن آیتم به آبجکت، return true هست. اگر هم بخوایم که این اضافه شدن انجام نشه، کافیه یه مقدار Falsy ریترن کنیم.مقادیر Falsy در جاوااسکریپت: undefined, null, false, 0, &#x27;&#x27;NaNنمونه لایو از کد بالا رو توی کدپن گداشتم تا ببینید: http://codepen.io/farskid/pen/YZorLG/ Deep Freeze کردن آبجکت ها با استفاده از Proxyیکی دیگه از کارهایی که میشه با Proxy انجام داد، جلوگیری از تغییر یه آبجکت در جاوااسکریپته.یعنی Proxy بهمون اجازه میده Immutable Data بسازیم.درسته که توی نسخه ES6، عبارت Const معرفی شد، اما این عبارت مثل زبان های دیگه که در اونها یه ثابت (Constant) میسازه، عمل نمیکنه. به عبارتی دیگه نباید انتظار داشته باشیم که Const برامون ثابت بسازه. برای اطلاعات بیشتر میتونید به لینک های زیر سر بزنین:ES6 constES6 const is not immutableدر مورد Object.freeze هم ایراد وارده جون فقط یه لول از آبجکت رو فریز میکنه.let testObj = Object.freeze({id: 1, name: {first: &#039;Farzad&#039;}})

testObj.id = 2 // Would&#039;nt affect the testObj.id
testObj.name.first = &#039;Ali&#039; // Changed testObjوقتی یه آبجکت Freeze میشه یعنی دیگه نمیشه آیتم های درونش رو عوض کرد. در صورتی که توی اون آبجکت، آبجکت های دیگه ای هم وجود داشته باشن و از تغییر اونا هم جلوگیری کنیم، اسمش میشه Deep Freeze.بریم سراغ کد و یه هندلر بنویسیم. بیایم اسم هندلرمون رو بزاریم rejector، چون تغییراتی که باید روی آبجکتمون رخ بدن رو reject میکنه.// Create a freeze factory
const freezeObjectFactory = (obj) =&gt; {

  // Our handler that rejects any change to the object and any nested objects inside it
  const rejector = {
    get(obj, prop) {

      // If dealing with nested object, nest the proxy untill it reaches the direct property of it&#039;s parent proxy
      if (typeof obj[prop] === &#039;object&#039; &amp;&amp; obj[prop] !== null) return new Proxy(obj[prop], rejector)
 
      // If prop is directly accessible, just do the default operation
      else return obj[prop]

    },

    set(obj, prop, val, rec) {

      console.warn(`Can not set prop ${prop} on freezed object`)
 
      // Return the proxy itself.
      // Note that we could return false, since returning false will create a TypeError, the latter code would always have to be inside a try-catch block which is immpossible and not flexbile.
      return rec
 
    }
  }
}

// Now let&#039;s use it and put it into test
// Start our object with default values
let testObj = freezeObjectFactory({name: &#039;Farzad&#039;, parent: {father: {name: &#039;Ali&#039;}}})

// try to change values
testObj.name = &#039;John&#039; // Can not set prop name on freezed object

testObj.parent.father.name = &#039;Mark&#039; // Can not set prop name on freezed object

testObj.id = 1 // Can not set prop id on freezed object

console.log(testObj) // Still the same object as defined above

خب برای اینکه آبجکت هامون رو Freeze کنیم، اولش یه فکتوری ساختم که اگر آبجکتمون رو بهش پاس بدیم، پراکسی شده آبجکتمون رو بهمون میده که دیگه قابل تغییر نیست.متد Get هندلرمون چک میکنه، اگر آیتمی که داریم میخونیمش مستقیم توی خود آبجکت قرار داره همونو بهمون میده. در غیر این صورت به این معنیه که توی یه آبجکت درونی قرار گرفته. ما تنها آبجکت بیرونی رو از پراکسی گذروندیم، یعنی اگر بخوایم آیتم های درونی مثل testObj.parent.father.nameرو ست کنیم دیگه متد Set فراخوانی نمیشه تا جلوی تغییر مقادیر گرفته بشه. پس تا وقتی که با آیتم های تودرتو طرفیم باید اونارو به صورت داخلی از پراکسی بگذرونیم. این توضیح، خط اول متد get رو کامل روشن میکنه.در متد Set هم باید دقت کنیم پارامتر ۴ام این متد همون آبجکتی هست که در ابتدا به پروکسی پاس داده شد یعنی{name: &#039;Farzad&#039;, parent: {father: {name: &#039;Ali&#039;}}}پس میتونیم همون رو ریترن کنیم. دقت کنید توی کامنت توضیح داده شده که اگر return false کنیم اونوقت پراکسی TypeError ریترن میکنه و این یعنی اگر Exception اش گرفته نشه برنامه خط های بعدی رو ادامه نمیده و خارج میشه. این به این معنیه که خط های بعدی باید کلا در یه بلاک try-catch قرار بگیره که غیر ممکن و مسخره اس. پس به جای return false ما خود آبجکت رو ریترن میکنیم.نمونه کد بالا روی توی کدپن گذاشتم تا راحت تر تستش کنین: http://codepen.io/farskid/pen/bqzxRv/ ساخت آبجکت های دفاعی با استفاده از Proxyآبجکت دفاعی یه تعریف خودساخته اس از آبجکتی که فقط آیتم جدید و غیر تکراری قبول میکنه. در صورتی که بخواین مقدار موجود در آبجکت رو تغییر بدین جلوتون رو میگیره. اما اگر بخواین یه آیتم غیرتکراری جدید بهش اضافه کنین،‌ کاری بهتون نداره.مثلا فرض کنید آبجکتمون let myObj = {name: &#x27;Farzad&#x27;, siblings: 1} هست. اگر بخوایم آیتم siblings رو آپدیت کنیم، جلومون رو میگیره جون siblings وجود داره. اما اگر بخوایم مثلا myObj.age = 25 رو انجام بدیم مشکلی نداره چون age وجود نداره.چون این شرایط خیلی به شرایط قبلی نزدیکه (Deep Freeze)، همون کد رو ویرایش میکنیم.// Create a defensive factory
const defensiveObjectFactory = (obj) =&gt; {

  // Our handler that rejects any change to the object and any nested objects inside it
  const rejector = {
    get(obj, prop) {

      // If dealing with nested object, nest the proxy untill it reaches the direct property of it&#039;s parent proxy
      if (typeof obj[prop] === &#039;object&#039; &amp;&amp; obj[prop] !== null) return new Proxy(obj[prop], rejector)
 
      // If prop is directly accessible, just do the default operation
      else return obj[prop]

    },

    set(obj, prop, val, rec) {

      // This time we traverse the object tree to see whether it contains prop or not
 
      // If prop is not currently present in obj, add it
      if (!(prop in obj)) {
        obj[prop] = val
        return true
      }

      // Else warn about it and prevent assignment
      console.warn(`Can not set prop ${prop} on freezed object`)
 
      // Return the proxy itself.
      // Note that we could return false, since returning false will create a TypeError, the latter code would always have to be inside a try-catch block which is immpossible and not flexbile.
      return rec
 
    }
  }
}

// Now let&#039;s use it and put it into test
// Start our object with default values
let testObj = freezeObjectFactory({name: &#039;Farzad&#039;, parent: {father: {name: &#039;Ali&#039;}}})

// try to change values
testObj.name = &#039;John&#039; // Can not set prop name on freezed object

testObj.parent.father.name = &#039;Mark&#039; // Can not set prop name on freezed object

testObj.id = 1 // In this case it could be added cause id is new

console.log(testObj) // not the same object, it has `id` on itاینبار اول چک میکنیم اگر آیتم درون آبجکت وجود نداشته باشه به آبجکت اضافه میشه مثل testObj.id. اما جلوی تغییر آیتم های از پیش قرار گرفته مثل name رو میگیریم.نمونه در کدپن: http://codepen.io/farskid/pen/OpemdQ/ جمع بندیتوی این مطلب با Proxy در جاوااسکریپت آشنا شدیم و فهمیدیم که بهمون اجازه میده عملکردهایی مثل خوندن یه آیتم و اضافه کردن آیتم جدید به آبجکت رو کنترل کنیم. درست مثل کاری که Proxy های شبکه ای برامون انجام میدن. کاربردهایی که از Proxy جذاب بودن رو هم با هم مرور کردیم مثل Deep Freeze کردن یه آبجکت یا Defensive کردن آبجکت ها. همینطور یاد گرفتیم که میتونیم تغییرات روی یه آبجکت رو با Proxy ردیابی کنیم و شبیه سازی ای از Object.observe رو بسازیم.proxyاگر از خوندن این مطلب لذت بردین میتونین اونو با دیگران به اشتراک بزارید. همینطور میتونین از سایر مطالب بلاگ هم استفاده کنین و یا اگر دوس داشته باشید، کنارمون بنویسید. برای انتشار مطلب در پول ریکوئست میتونید با ما درتماس باشید.</description>
                <category>فرزاد یوسف زاده</category>
                <author>فرزاد یوسف زاده</author>
                <pubDate>Sun, 09 Apr 2017 04:17:11 +0430</pubDate>
            </item>
                    <item>
                <title>مینیفای کردن HTML و CSS در جکیل (Jekyll)</title>
                <link>https://virgool.io/pullrequest/%D9%85%DB%8C%D9%86%DB%8C%D9%81%D8%A7%DB%8C-%DA%A9%D8%B1%D8%AF%D9%86-html-%D9%88-css-%D8%AF%D8%B1-%D8%AC%DA%A9%DB%8C%D9%84-jekyll-oq1ajoexgjec</link>
                <description>برای بالا بردن سرعت لود وب سایت ها از تکنیک مینیفای کردن محتوای وب سایت استفاده میشه. مینیفای کردن محتوا به این معنیه که خروجی HTML وب سایت، فایل های CSS و JS ای که در سورس وب سایت قرار دارن رو با حذف فاصله های اضافی (whitespace) و سایر فنون (نمیخوام وارد جزییاتش بشم چون از حوصله این مطلب خارجه :دی) به کمترین حجم ممکنش میرسونن.برای اینکار روی بلاگ (ورژن قدیم) پول ریکوئست دنبال راه حل میگشتم. اولش این راه به نظرم رسید که محیط کاری پروژه (Project Workflow) رو ببرم روی گرانت (Grunt). با اینکار میتونستم هم از مینیفای کردن است (Asset) های CSS و JS استفاده کنم و هم اینکه مثلا این استها رو ورژن بندی کنم تا کش مرورگرها رو کنترل کنم و هم اینکه عکس ها رو بهینه سازی کنم و …اما از ابتدا تصمیم گرفتم پروژه رو به هیچ تسک اتومیتری مثل گرانت یا گالپ وابسته نکنم چون کار با جکیل به ذات ساده اس و نمیخواستم پیچیده اش کنم. :پیاگه با جکیل کار کرده باشین حتما میدونین که جکیل برای کنترل محتوا از مفهومی به اسم لی اوت استفاده میکنه. با استفاده از لی اوت های جکیل میشه انواع مختلفی از صفحات رو ساخت. مشابه همین کار رو توی وردپرس مفهوم Custom Page داره انجام میده. اما تفاوتش با جکیل در اینه که توی جکیل، هر لی اوت مثل یه Pure Function عمل میکنه. محتوا (یا بخشی از محتوا) رو میگیره و تحت منطقی که میتونین براش تنظیم کنین، خروجی میده.با جستجوی بیشتر به دنبال راه حل برای مینیفای کردن محتوای خروجی در جکیل، یه پروژه ای پیدا کردم که یه لی اوت ساخته و توی اوت لی اون محتوا رو دستکاری کرده و مثلا WhiteSpace ها رو حذف کرده.البته تنظیمات این لی اوت دست شماست و API کوچیکی برای سفارشی کردنش بهتون داده.برای دیدن مستندات پروژه میتونین از لینک دسترسی به پروژه jekyll-compress-html استفاده کنین.روش استفادهکافیه فایل لی اوت رو توی پوشه _layouts پروژه اتون قرار بدید و در بالاترین و اصلی ترین لی اوت بلاگتون (به صورت پیشفرض این همون layout: default هست)، ریفرنسی به لی اوت Compress بدید. مثلا FrontMatter لی اوت اصلی بلاگ پول ریکوئست این شکلیه:---
layout: compress
---

&lt;!DOCTYPE html&gt;
&lt;html&gt;با اینکار خروجی اصلی بلاگتون میرسه به لی اوت کامپرس و اونو مینیفای شده به عنوان سورس وب سایت خروجی میده. برای دیدن نمونه لایو ازین کار میتونید سورس صفحه فعلی رو توی مرورگرتون ببینین. :دیسورس مینیفای شده پول ریکوئستهمیشه برای هرکاری نیاز به پلاگین نیست. گاهی اوقات ابزار هست فقط باید ازشون درست استفاده کنیم.</description>
                <category>فرزاد یوسف زاده</category>
                <author>فرزاد یوسف زاده</author>
                <pubDate>Mon, 03 Apr 2017 03:47:33 +0430</pubDate>
            </item>
                    <item>
                <title>تجربه های کاربری (UX) ضروری در اپلیکیشن های موبایل که به ندرت رعایت میشن</title>
                <link>https://virgool.io/pullrequest/%D8%AA%D8%AC%D8%B1%D8%A8%D9%87-%D9%87%D8%A7%DB%8C-%DA%A9%D8%A7%D8%B1%D8%A8%D8%B1%DB%8C-ux-%D8%B6%D8%B1%D9%88%D8%B1%DB%8C-%D8%AF%D8%B1-%D8%A7%D9%BE%D9%84%DB%8C%DA%A9%DB%8C%D8%B4%D9%86-%D9%87%D8%A7%DB%8C-%D9%85%D9%88%D8%A8%D8%A7%DB%8C%D9%84-%DA%A9%D9%87-%D8%A8%D9%87-%D9%86%D8%AF%D8%B1%D8%AA-%D8%B1%D8%B9%D8%A7%DB%8C%D8%AA-%D9%85%DB%8C%D8%B4%D9%86-tktg1vpno4i0</link>
                <description>زمانی که اپلیکیشن تلگرام وارد اپ استورها شد من هم مثل سایر کاربران وایبری اون زمان رفتم سراغ این پیام رسان. از اون زمان تا به الان هرگز از این مهاجرت به تلگرام پشیمون نشدم و این رضایت (رضایت کاربر)رو یکی از دستاوردهای طراحی نرم افزار تیم تلگرام میدونم. بی شک این موفقیت نتیجه دقت به طراحی و رعایت استانداردهای تجربه کاربری بوده و هست.اینکه چرا این داستان رو مطرح کردم دلیلش این بود که پیام رسان تلگرام یکی از معدود نرم افزارهای موبایلی ای هست که زیبایی در طراحی و یکپارچه بودن تفکر سیستمی رو میشه درش احساس کرد. هم چنین رعایت بعضی از تجربیات کاربری ضروری در این نرم افزار شدیدا علاقه من نسبت بهش رو دوچندان کرده.تجربیات کاربری ضروری برای طراحی اپلیکیشن های موبایلی شامل لیست طولانی ای از مواردی میشه که یه توسعه دهنده باید تا جایی که میتونه اونو رعایت کنه تا رضایت کاربرانش رو فراهم کرده باشه. در این چند سالی که بازار داغ اپلیکیشن های موبایل در ایران به راه بوده من صدها نرم افزار ساخته شده توسط توسعه دهنده های ایرانی رو نصب و حذف کردم. از دلایل اصلی حذف این نرم افزارها عدم رعایت UX درست بوده. زمانی که میون کار با نرم افزار با زدن دکمه Back گوشی های اندرویدی از نرم افزار خارج میشین و بعد از برگشتن به نرم افزار مراحل ریست شدن و باید اونا رو از اول طی کنین، تازه متوجه میشین که توسعه دهنده وطنی چه زیبا دقایقی نه چندان کوتاه از زمان ارزشمندتون رو حروم کرده.سوال: حالا این تجربیات ضروری چیا هستن؟مورد اول: کنترل دکمه Back (بازگشت) برای نرم افزارهای اندرویدیچرا اندرویدی؟ چون iOS مفهومی به اسم Back Button نداره.اصولا نرم افزار های موبایلی ساده هستن و شامل چند صفحه بندی نه چندان تودرتو (nested views). در چنین نرم افزارهایی انتظاری که میره اینه که اگر شما با کلیک روی دکمه یا لینکی وارد یه صفحه جدید شدید، با زدن دکمه بازگشت گوشی موبایلتون، نرم افزار شما رو برگردونه به صفحه قبلی. حالا زمانی که صف صفحات قبلی تموم بشه چی؟ این معمولا زمانی اتفاق میوفته که به صفحه اصلی یا ابتدایی نرم افزار میرسیم. الگوی معمولی که توی نرم افزارهای زیادی دیدم این بوده که با زدن دکمه بازگشت نرم افزار بهتون یه نوتیفیکیشن نشون میده که اگر بار دیگه دکمه بازگشت رو بزنین از نرم افزار خارج میشین.اینکه رعایت میشه،‌ پس چرا میگی به ندرت؟ :سوالعبارت به ندرت رو برای این موارد استفاده از دکمه بازگشت به کار نبردم. اصولا رعایت این لایه از تجربیات توی اکثر نرم افزارها دیده میشه. چیزی که رعایت نمیشه UX های ضروری تره :پیمشکل اصلی اون زمای پیش میاد که توسعه دهنده یه Overlay نشون میده. overlay در طراحی نرم افزارهای موبایلی به محتوایی گفته میشه که روی محتوای اصلی نشون داده میشه. Overlay میتونه هر یک از Popup, Popover, Modal, Notification, Action Sheet یا Drawer باشه.از ضروری ترین UX ها، بستن Overlay های باز شده با زدن دکمه بازگشت هست.در حقیقت با هر کدوم از Overlay های باز شده باید مثل یه صفحه باز شده برخورد کرد و اونها رو به صف صفحات باز شده اضافه کرد تا با زدن دکمه بازگشت علاوه بر صفحات باز شده، Overlay های باز شده هم بسته بشن.اگر تلگرام تون رو باز کنید و منوی سمت چپ کشویی رو هم باز کنید، با زدن دکمه بازگشت موبایلتون میبینید که این منو بسته میشه.بسته شدن Overlay های باز شده با دکمه بازگشت در تلگراممورد دوم: استفاده از دکمه طرد شده Menu Buttonمیشه گفت شاید ۱درصد از نرم افزارهای اندرویدی که توی اپ استورهای داخلی و خارجی موجودن، از دکمه Menu Button در نرم افزارشون استفاده کردن. دکمه Menu Button دکمه ای هست که در حقش جفای زیادی شده. برای استفاده از این دکمه استاندارد خاصی موجود نیست برای همین در برندهای مختلف کارایی این دکمه متفاوته. مثلا در گوشی های Huawei این دکمه برای نشان دادن برنامه های باز استفاده میشه اما در برند Lenovo این دکمه برای نشون دادن تم های گوشی استفاده میشه!! تفاوت رو ببینید!!! :پوکرفیسیکی از کاربردهای زیبای این دکمه میتونه نشون دادن لیست گزینه های بیشتر در نرم افزار باشه. اگر در مرورگرهای گوگل کروم و فایرفاکس اندرویدی روی این دکمه تپ کنید، میبینید که لیست طولانی ای از گزینه های مرورگر رو نشونتون میدن. در نرم افزار مورد بحثمون یعنی تلگرام هم از این دکمه به خوبی استفاده شده. در نسخه های ابتدایی زمانی که توی یه چت از این دکمه استفاده میکردید، گزینه های چت در سمت راست بالا نمایش داده میشد.بسته شدن Overlay های باز شده با دکمه بازگشت در تلگرامدر نسخه های جدید علاوه بر این، در صفحه لیست چت ها، با استفاده از دکمه منو، دراور کشویی (سایدمنو) هم باز میشه و طبق نکته ای که توی مورد اول گفته بودم، با استفاده از دکمه بازگشت این منو بسته میشه.نتیجه گیریمطمئنا موارد بیشتری میشه برای اجرای UX های نرم افزارهای موبایلی پیدا کرد و اشتباهات مرسومی که در اجراشون صورت گرفته رو مورد بررسی قرار داد. استفاده از نکات UX در تولید محتوای مفید خیلی ضروریه. یادمون باشه:نکات ریز در رعایت تجربه های کاربری میتونه رضایت کاربرانتون رو به همراه داشته باشه و هر کاربری رو به یه کاربر وفادار تبدیل کنه</description>
                <category>فرزاد یوسف زاده</category>
                <author>فرزاد یوسف زاده</author>
                <pubDate>Thu, 30 Mar 2017 03:42:53 +0430</pubDate>
            </item>
                    <item>
                <title>نگه داشتن فوتر در پایین صفحه مستقل از ارتفاع محتوا</title>
                <link>https://virgool.io/pullrequest/%D9%86%DA%AF%D9%87-%D8%AF%D8%A7%D8%B4%D8%AA%D9%86-%D9%81%D9%88%D8%AA%D8%B1-%D8%AF%D8%B1-%D9%BE%D8%A7%DB%8C%DB%8C%D9%86-%D8%B5%D9%81%D8%AD%D9%87-%D9%85%D8%B3%D8%AA%D9%82%D9%84-%D8%A7%D8%B2-%D8%A7%D8%B1%D8%AA%D9%81%D8%A7%D8%B9-%D9%85%D8%AD%D8%AA%D9%88%D8%A7-ulkomodnqko0</link>
                <description>چند وقت پیش توی یکی از گروه های تلگرامی که برای توسعه دهنده های جاوااسکریپت ساخته شده بحثی شد مبنی بر اینکه مشکل فوتر ثابت در پایین صفحه رو چطور میشه حل کرد؟ حالا مشکل این بود که میخواستن فوتر رو حتی توی صفحاتی که محتوای کمی دارن توی پایین صفحه نگهش دارن.عکس زیر رو ببینید تا کامل مشکلی رو که توضیح دادم درک کنید.فوترجالبه بدونین که توی طراحی بلاگ پول ریکوئست هم به این مشکل برخوردم و برای حاشیه راه نسبتا ساده به ذهنم رسید. توی گروه تلگرامی دیگران داشتن در مورد فلکس باکس و جاوااسکریپت صحبت میکردن. درسته فلکس باکس میتونه این مشکل رو حل کنه اما مشکلش اینه که ساپورتش برای همه مرورگرها کامل نیست. کنترل این موضوع با جاوااسکریپت هم خیلی Overkill هست و تلاش برای بهایی ناچیزه.راه حلبرای حل این موضوع باید مارک آپ اچ تی ام ال رو به صورتی خاص بچینید. در این مارک آپ المنت مربوط به فوتر رو بیرون از کانتینر اصلی وب سایت که محتوا رو در اون قرار میدید،‌نگه دارید. به تکه کد اچ تی ام ال زیر دقت کنین:&lt;html&gt;
 &lt;!-- ... --&gt;
  &lt;body&gt;
    &lt;div class=&quot;wrapper&quot;&gt;
      &lt;!-- All Website Content --&gt;
    &lt;/div&gt;
    &lt;footer class=&quot;footer&quot;&gt;&lt;/footer&gt;
  &lt;/body&gt;
&lt;/html&gt;خب برای اینکه فوتر همیشه پایین محتوا باشه باید با Absolute Positioning اون رو محدود کنیم.* {
  box-sizing: border-box; // اگر این خط رو اعمال نکنید این روش کار نمیکنه
}
html {
  height: 100%;
}
body {
  padding-bottom: 56px; // هم اندازه ارتفاع فوتر
  position: relative;
  min-height: 100%; // برای اینکه فوتر، حتی زمانی که محتوای کافی توی صفحه نداریم،‌پایین صفحه باقی بمونه
}
.footer {
  position: absolute;
  bottom: 0;
  left: 0;
  width: 100%;
  height: 56px // دقت کنید این اندازه باید با پدینگ پایین body یکسان باشه
}برای اینکه احساس واقعی ای ازین تکنیک داشته باشید،‌این کد ها روی توی کدپن قرار دادم تا بتونین دموی زیر رو ببینید. در ضمن این راه حل مشکلی با ریسپانسیو لی اوت نداره و به خودی خود ریسپانسیو هست. https://codepen.io/farskid/pen/JWZzaO مشکل راهی که گفتیم چیه؟این راه یه مشکل کوچولو داره و اونم اینه که برای زمانی مناسبه که ارتفاع دقیق فوتر مشخص باشه. دوست عزیزمسعید علیپور راه دیگه ای رو پیشنهاد داد که حتی برای زمانی که ارتفاع دقیق فوتر مشخص نیس میشه ازش استفاده کرد.توی این راه از Table Layout در CSS استفاده کرده تا بتونه کل کانتینر وب سایت و فوتر رو دو سطر متوالی و جدا از هم در یه جدول درنظر بگیره. چون ماهیت فوتر در این روش از جنس سطر جدوله، به اندازه محتوا بزرگ میشه و نیازی نیس ارتفاع دقیقش رو بدونیم.دقت کنید که مارک آپ HTML رو به table تغییر ندید. فقط کافیه شبکه بندی با جدول رو با استفاده از CSS شبیه سازی کنیم.&lt;div class=&quot;wrapper&quot;&gt;

&lt;/div&gt;
&lt;div class=&quot;footer&quot;&gt;
    &lt;div&gt;
        I am a flexible sticky footer.
        &lt;br&gt;
        Feel free to change my height.
    &lt;/div&gt;
&lt;/div&gt;html, body {
    height: 100%;
}
body{
    min-height: 100%;
}
body {
    display: table;
    width: 100%;
    height: 100%;
}
.wrapper{
    background-color: green;
}
.footer, .wrapper {
    display: table-row;
}
.footer {
    height: 1px;
}

.footer {
    background: #e5e5e5;
}
.footer&gt;div{
    padding: 10px;
    text-align: center;
}اینم یه دموی لایو از خلاقیتی که سعید انجام داده: http://codepen.io/saeedalipoor/pen/EWJovr/ </description>
                <category>فرزاد یوسف زاده</category>
                <author>فرزاد یوسف زاده</author>
                <pubDate>Sun, 26 Mar 2017 03:07:03 +0430</pubDate>
            </item>
                    <item>
                <title>سی اس اس ماژولار برای پروژه های بزرگ</title>
                <link>https://virgool.io/pullrequest/%D8%B3%DB%8C-%D8%A7%D8%B3-%D8%A7%D8%B3-%D9%85%D8%A7%DA%98%D9%88%D9%84%D8%A7%D8%B1-%D8%A8%D8%B1%D8%A7%DB%8C-%D9%BE%D8%B1%D9%88%DA%98%D9%87-%D9%87%D8%A7%DB%8C-%D8%A8%D8%B2%D8%B1%DA%AF-fqx6t78gqvrq</link>
                <description>نوشتن سی اس اس خیلی ساده اس. به سادگی تغییر رنگ و سایز فونت متن. تقریبا هرکسی میتونه سی اس اس بنویسه و از اون تقریبا همه، حداقل ۸۰درصد به هرنحوی هست کارشونو باهاش تموم میکنن و راضی هم هستن. اما نوشتن و مدیریت کردن سی اس اس به صورت استاندارد و درست و به دور از درد و خونریزی!! یکی از سخت ترین تسک های توسعه فرانت انده.از اونجایی که توی سی اس اس عملا ارور هندلینگی نداریم و استاد سی اس اس خیلی سایلنت از کنار ارورها و کانفلیکت ها میگذرن، توی هر پروژه ممکنه ساعت ها زمان بزاریم تا بتونیم متوجه بشیم که چرا سایز فونت این دکمه شده ۱۳.۷۲ پیکسل!!!به دلایلی که گفتم و به خاطر خدا (For the sake of GOD) پیروی از یه الگوی استاندارد برای پیاده سازی استایل های پروژه و به همین نسبت پیاده سازی ساختار مارک آپ اچ تی ام ال،‌ خیلی خیلی مهمه. با پیروی از یه استاندارد خوب توی کارهای گروهی هم تسک ها ساده تر پیش میرن و هم مشکلاتی از قبیل عدم هماهنگی و طرز تفکر متفاوت بین اعضای تیم پیش نمیاد. مشکلاتی که حتی توی یه پروژه یه نفره که خودتون هم توسعه دهنده اش هستید گریبان گیرتون میشه چه برسه به یه پروژه که بالغ بر ۸۰ توسعه دهنده میتونن براش استایل بزنن و سی اس اس بنویسن.خوشبختانه مثل سایر مشکلات در دنیای نرم افزار، پیش از ما دیگران هم به این مشکل برخوردن و براش اتفاقا راه حل های خیلی خوبی هم پیشنهاد دادن. استانداردهایی از قبیل BEM, OOCSS, SMACSS, Atomic Design.خب برای حل این مشکل چیکار کنم؟خب فرض میکنیم که تصمیم گرفتیم برای پروژه بعدی از این استانداردها پیروی کنیم. قبلا درگیر این بودیم که نمیدونیم باید چیکار کنیماما حالا درگیر این شدیم که اصلااز کدوم استاندارد باید پیروی کرد؟؟از همه استانداردها پیروی کنم؟ فقط از یکیشون پیروی کنم؟ خودم بیام یه استاندارد برای خودم پیدا کنم؟ این استانداردها رو ترکیب کنم؟من در شروع کار با این استانداردها فقط از BEM استفاده میکردم اما به دلیل برخی کمبودهایی که در این استاندارد احساس کردم رفتم سراغ دیگری. اما در نهایت بعد از امتحان کردن همه این استانداردها به ترکیبی از اونها رسیدم که برام خیلی خوب کار میکنه. ازونجایی که بعد از پیدا کردن این ترکیب مشکلات قبلیم رفع شد، تصمیم گرفتم اونو باهاتون به اشتراک بزارم.پارامترهای یک معماری استاندارد سی اس اسیبه نظرم ۴ پارامتر در یک استاندارد صحیح از قرارداد سی اس اسی مهم ان و باید رعایت بشن. یه استاندارد صحیح و درسته تنها زمانیکه بعد از استفاده ازون در پروژه اتون:با یه نگاه بتونم بفهمم با ویرایش استایل های یک کلاس، تنها اون کلاس رو تغییر دادم و مشکلی ناخواسته برای سایر قسمت های پروژه ایجاد نکردم.با یه نگاه بتونم بفهمم هر کلاس به کدوم قسمت از مارک آپ ام مرتبطه. یعنی کلاس ها و نام گذاری هاشون بتونن معنی منطقی ای از مارک آپ توی ذهنم ایجاد کنن.کلاس های سی اس اس تا جایی که ممکنه باید کمترین تغییر در تصوری که از اچ تی ام ال اونها به وجود میاد رو اعمال کنن. (میدونم جمله مبهمیه، بیشتر توضیح میدم بعدا)با یه نگاه بتونم تشخیص بدم که این کلاس داره توی جاوااسکریپت استفاده میشه یا نه. اینطوری مطمئن میشم اگر استایلش رو تغییر بدم هیچ منطق جی اسی خاصی رو از کار ننداختم.شروع از BEMاستاندارد BEM پایه این ترکیبه. اگر قبلا با BEM کار نکردین و یا اسمش رو نشنیدین، باید بدونید کهعبارت BEM یه مخففه از:B: BlockE: ElementM: Modifierاگه برای اولین بار به نوع نام گزاری خاصی که برای کلاس های سی اس اسی توی این استاندارد درنظر گرفته میشه نگاه کنین، ممکنه فکر کنین خیلی زشت و ترسناکه!.block { /* styles */ }
.block__element { /* styles */ }
.block--modifier { /* styles */ }خلاف ترسناک و عجیب بودن این نوع نام گزاری، BEM خیلی قدرتمنده. اجازه بدین با یه توضیح مختصر از این نام گزاری بیشتر آشناتون کنم باهاش.BEM میگه هرچیزی توی سی اس اس یا بلاکه یا المنته یا مودیفایر.Block چیه؟هر کامپوننت مجزا یه بلاکه. مثلا اگر بخواین یه فرم تماس بسازین، فرم یه بلاکه. توی استاندارد BEM هر بلاک به صورت منطقی و نرمال نامگزاری میشه. مثلا .form یا .modal.حالا چرا BEM میگه برای یه بلاک کلاس درنظر بگیریم و مثلا نیایم به المنت form استایل بدیم اینه که وابستگی مارک آپ به استایل رو کمتر کنه. شاید جایی شما نیاز داشته باشین از استایل یه فرم استفاده کنین و نه خود فرم!معمولا دکمه ها در یه پروژه مثال خوبی از بلاک هستن که استایل های متفاوتی هم به خودشون میگیرن. اگر بیاین رنگ بک گراند المنت button رو قرمز کنین، اونوقت همه ی button ها این استایل رو به ارث میبرن. بعد اگر جای دیگه نخوایم دکمه مون بک گراند قرمز داشته باشه باید اونو overwrite کنیم. overwite کردن های پیاپی در سی اس اس یه آنتی پترنه که اگر دچارش بشین کار رو براتون خیلی سخت میکنه.button {  background-color: red; }
.something button {  background-color: blue; /* ? */ }ولی اگر به جای استایل دادن به المنت button به کلاس .button استایل بدین، میتونین نوع دیگری از دکمه ها رو برای کیس های مختلف استایل بزنین. این پترنیه که توی کتابخونه های معروفی مثل Bootstrap هم میبینیم.انواع مختلف یه بلاک میشه قسمت بعدی تعریف BEM یعنی Modifier ها.Modifier چیه؟مودیفایر یه جور فلگه برای نشون دادن حالت های مختلف یه بلاک. اگر به همون مثال دکمه ها برگردیم و استایل های مختلف دکمه ها در Bootstrap رو مثل بزنیم:در بوت استرپ ۴ حالت برای دکمه ها درنظر گرفته شده مانند .btn-primary.با استفاده از اصل نامگزاری مودیفایر حالت متفاوت یه بلاک با علامت -- نشون داده میشه. مثلا.button--primary.اگر بلاکی دارای مودیفایر باشه الگوی صحیح اینه که استایل های مشترک رو به کلاس بلاک بدین و استایل های مختص هر حالت رو به مودیفایر اون حالت بدین. مثال زیر رو ببینید:.button {
  display: inline-block;
  border: 1px solid #4183C4;
  background-color: #4183C4;
  color: #fff;
  padding: .5em .75em;
}
/* modifiers */
.button--large {
  padding: 1em 1.5em;
}
.button--small {
  padding: .25em .5em;
}حالا که کامل متوجه شدین بلاک و مودیفایر به چی میگن بریم سراغ آخرین قسمت یعنی المنت ها.Element چیه؟المنت ها اجزای کلیدی بلاک هستن. مثلا تایتل و فوتر یه مودال. برای اینکه بگیم یه کلاس المنتی از یه بلاکه باید اونو با علامت __ اسم گزاری کنیم.اگر همون مثال دکمه ها رو ادامه بدیم، فکر کنین به دکمه ها استایل دادیم و انواع مختلف دکمه ها رو هم با مودیفایر ها تعریف کردیم. حالا میخوایم گروهی از دکمه های کنار هم درست کنیم مثل این شکل:Button Groupsتوی این مثال کل گروه دکمه ها یه بلاکه. دکمه های این گروه هرکدوم یه المنت هستن و دکمه های گوشه های راست و چپ، با مودیفایر مشخص میشن. طبق توضیحاتی که تا اینجا از BEM بهتون دادم نامگزاری ها میتونه به این صورت باشه:کل بلاک .btngroupهر المنت .btngroup__buttonدکمه های گوشه راست و چپ .btngroup--rightbtn, .btn-group--leftbtnشرط میبندم الان دیگه این نوع نامگزاری براتون ترسناک نیست و کاملا هم منطقی به نظر میاد. در بلند مدت و در پروژه های بزرگ، هرچقدر بیشتر به این استاندارد تکیه کنید، کار رو برای خودتون و همکارانتون در آینده راحت تر کردید. پیروی از این استاندارد نه تنها نامگزاری ها رو یکدست میکنه بلکه نقش هر کلاس رو شفاف تر هم میکنه و خیلی راحت میشه از روی فایل سی اس اس، یه داکیومنتیشن خوب از استایل های پروژه ساخت.نکته خاصی در مورد المنت های BEMیادتون باشه، اگر تو پیروی از استاندارد BEM به جایی رسیدین که اسم یه کلاس رو گذاشتین .btngroup__button__innertext مطمئن باشین که دارین اشتباه بزرگی میکنین. اسم های طولانی و چندقسمتی در BEM معمولا نشونه اشتباه در منطق تون هستن. برای اینکه با روش های حل این مشکل بیشتر آشنا بشین، به مطلبی که قبلا در این مورد نوشتم رجوع کنین.گذر از BEM و ترکیب با سایر استانداردهاتوی استاندارد BEM اگر دقت کرده باشین حرفی از لی اوتینگ زده نمیشه. BEM همه چیز رو در یکی از سه نقش بلاک، المنت یا مودیفایر خلاصه میکنه. اما اگر وب سایت طراحی کرده باشید حتما متوجه شدین که گاهی اوقات بعضی از اجزای یه لی اوت توی این ۳تا خلاصه نمیشه. مثل کانتینرها.به عکس زیر از سایت Sussy نگاه کنید:Susyبه تجربه برام ثابت شده در طراحی لی اوت این عکس مارک آپ اچ تی ام ال زیر مناسبه:&lt;section&gt;
  &lt;div class=&quot;l-wrap&quot;&gt;
    &lt;div class=&quot;block&quot;&gt;
       &lt;!-- ... --&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/section&gt;ولی سوالی که پیش میاد اینه که تگ section باید چه کلاسی بهش داده بشه؟ باید المنتی از والدش باشه؟ یا نه، باید خودش یه بلاک باشه؟ اصلا اون کلاس l-wrap چیه؟خب برای دونستن جواب سوال های بالا توضیحات کاملی در مورد NameSpacing باید بدم که میتونین اون رو در قسمت دوم این مطلب دنبال کنید.جمع بندیتوی این مطلب راجع به مشکلات کار با سی اس اس بدون یه استاندارد مناسب صحبت کردیم و فهمیدیم که بدون استاندارد کار تیمی خیلی سخت میشه. برای حل این مشکل رفتیم سراغ استاندارد BEM و اونو شناختیم. درنهایت هم رسیدیم به مرحله ای که ‌BEM رو با ترکیبی از استانداردهای لی اوت دیزاین تکمیل تر باید تکمیل کنیم تا به یه چارچوب جامع برسیم.این مطلب تنها شامل قسمت اول کل مفهوم سی اس اس برای پروژه های بزرگ بود. برای خوندن قسمت دوم این مطلب منتظر باشید.</description>
                <category>فرزاد یوسف زاده</category>
                <author>فرزاد یوسف زاده</author>
                <pubDate>Sat, 25 Mar 2017 03:07:03 +0430</pubDate>
            </item>
                    <item>
                <title>رفع مشکل نام های طولانی در BEM</title>
                <link>https://virgool.io/pullrequest/%D8%B1%D9%81%D8%B9-%D9%85%D8%B4%DA%A9%D9%84-%D9%86%D8%A7%D9%85-%D9%87%D8%A7%DB%8C-%D8%B7%D9%88%D9%84%D8%A7%D9%86%DB%8C-%D8%AF%D8%B1-bem-ppb8fkugzlp3</link>
                <description>BEM یکی از استانداردهای نام گذاری کلاس ها در سی اس اس هست. ممکنه براتون سوال باشه که مگه سی اس اس هم استاندارد نام گذاری نیاز داره؟ ۴تا دونه کلاس که ارزش این حرفا رو نداره! :دیاما باید بگم سی اس اس خیلی قلق داره و استفاده صحیح ازش در پروژه های نسبتا بزرگ بسیار سخته.برای بهتر متوجه شدن این موضوع کافیه به مطلبم در مورد سی اس اس ماژولار برای پروژه های بزرگ سری بزنین.مشکل اصلا کجاس؟در استاندارد BEM، گفته شده که برای نام گذاری اجزا و المنت های یک بلاک، از علامت __ استفاده میشه. یه فرم تماس رو در نظر بگیرید که مثل شکل زیر باشه:فرم تماستوی عکس مشخصه که برای طراحی این فرم بر اساس BEM باید نام گذاری های زیر انجام بشه:بلاک: کل فرم: .contactformالمنت: هر سطر از فرم: .contactform__rowحالا برای نام گذاری هر کدوم از اعضای درون یه سطر باید چیکار کرد؟ میتونیم یه اسم طبق استاندارد براش بزاریم مثلا .contactform__row__icon , ‍‍.contactform__row__userinputتوی مطلبم در مورد سی اس اس ماژولار برای پروژه های بزرگ گفتم که اگر در نامگذاری های BEM به حالتی رسیدین که دارین بیشتر از یک بار از __ استفاده میکنین مثلا حالت .contactform__row__icon بدنید که دارید اشتباه میکنید.نامگذاری اعضای بلاک نباید زنجیره وار به هم وصل باشهراه حلبرای حل این مشکل دو راه وجود داره:اسم های المنت های درونی رو به جای والد اول به والد اصلی بلاک ضمیمه کنینزمانی که این مشکل به وجود میاد، یه بلاک درونی بسازید و المنت رو توی این بلاک جدید قرار بدینوصل کردن المنت های درونی به والد اصلیدرسته که BEM به ما دیکته میکنه که کلاس المنت ها باید از فرمت block__element پیروی کنه ، اما محدودیتی وجود نداره که این بلاک توی کدوم رده از والد های اون المنت باشه. مثال زیر رو ببینید:فرض کنید میخوایم برای یه بلاگ استایل بزنیم و هر مطلب اون بلاگ از سه بخش header, body, footer تشکیل شده باشه. مارک آپ این مطلب در اچ تی ام ال این شکلی خواهد شد:&lt;article class=&quot;article&quot;&gt;
  &lt;header class=&quot;article__header&quot;&gt;
    &lt;h1 class=&quot;article__title&quot;&gt;&lt;/h1&gt;
  &lt;/header&gt;
&lt;/article&gt;ببینید به جای اینکه کلاس عنوان هدر رو بزاریم article__header__title، چون این اسم نامعتبره، عنوان رو به جای اتصال به والد اولش که article__header هست، به والد اصلی بلاک یعنی article وصل میکنیم. هیج تداخلی بین این نوع نامگذاری و قوانین BEM وجود نداره و معنی نامربوطی هم نسبت به مارک آپ توی ذهن ایجاد نمیکنه. پس کاملا روش معتبریه.ولی شرایطی هم هست که این روش جواب نمیده و باید بریم سراغ راه حل دوم. مثلا بلاک کامنت های همون بلاگی که مثالش رو دیدیم. فرض کنید سیستم کامنتینگ این بلاگ به صورت زیر باشه:&lt;section class=&quot;comments&quot;&gt;
  &lt;h2 class=&quot;comments__title&quot;&gt;&lt;/h2&gt;
  &lt;article class=&quot;comments__comment&quot;&gt;
    &lt;h3 class=&quot;comments__comment-title&quot;&gt;&lt;/h3&gt;
  &lt;/article&gt;
  &lt;article class=&quot;comments__comment&quot;&gt;
    &lt;h3 class=&quot;comments__comment-title&quot;&gt;&lt;/h3&gt;
  &lt;/article&gt;
 &lt;!-- ... --&gt;
&lt;/section&gt;اگر دقت کنین کلاس comments__comment-title یه کلاس نامعتبره و مثلا باید براش راه حلی پیدا کنیم. توی این شرایط چون کل بلاک کامنتها یه عنوان داره که کلاسش هم شده comments__title، دیگه نمیتونیم عنوان هر کامنت رو هم به والد بالاتر ارجاع بدیم. چون کلاسش با عنوان کل بلاک یکسان میشه درحالیکه دو المنت متفاوت هستن!توی این شرایط میریم سراغ راه حل دوم:ساخت بلاک های درونی جدیدتوی این راه میایم هر کامنت رو هم یه بلاک درنظر میگیریم و بهش کلاس .comment میدیم. دقت کنید توی این شرایط دیگه هر کامنت وابسته با والدش یعنی بلاک .comments درنظر گرفته نمیشه و استایل هاش به صورت مستقل بهش داده میشه.حالا نامگذاری عنوان هر کامنت کار ساده ایه. کلاس هرعنوان میشه ‍‍.comment__title به همین سادگی یه همین خوشمزگی :دیبا اینکه بلاک های .comments و .comment مستقل ازهم هستن،‌ اما استایل هاشون رو در یک فایل مثل _comments.scss ذخیره کنید تا محتوای استایل کامنت ها رو در یک نقطه متمرکز کرده باشید. اصل Single source of truthجمع بندیپیروی از قوانین خیلی خوبه اما مدیریت شرایطی که به دلیل این پیروی کار رو براتون سخت میکنن مهمه. یکی ازین شرایط در استفاده از BEM همین نامگذاری های زنجیره ای بود که راه حل هاش رو باهم بررسی کردیم.یادتون نره اگر کنجکاوین در مورد سی اس اس ماژولار بیشتر بدونین مطلب من در این مورد رو حتما مطالعه کنین.مطلبم در مورد سی اس اس ماژولار برای پروژه های بزرگامیدوارم از خوندن این مطلب لذت برده باشید.</description>
                <category>فرزاد یوسف زاده</category>
                <author>فرزاد یوسف زاده</author>
                <pubDate>Fri, 24 Mar 2017 03:07:03 +0430</pubDate>
            </item>
            </channel>
</rss>