<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
    <channel>
        <title>نوشته های Reza Hasani</title>
        <link>https://virgool.io/feed/@reza.hasani7899</link>
        <description>Head of Frontend Development at Dopely.top | Senior Frontend Engineer at Digikala.com</description>
        <language>fa</language>
        <pubDate>2026-06-16 21:04:12</pubDate>
        <image>
            <url>https://files.virgool.io/upload/users/55623/avatar/upjARC.png?height=120&amp;width=120</url>
            <title>Reza Hasani</title>
            <link>https://virgool.io/@reza.hasani7899</link>
        </image>

                    <item>
                <title>هرچیزی که درمورد bind و this در JavaScript و React باید بدونیم!</title>
                <link>https://virgool.io/Only-js/%D9%87%D8%B1%DA%86%DB%8C%D8%B2%DB%8C-%DA%A9%D9%87-%D8%AF%D8%B1%D9%85%D9%88%D8%B1%D8%AF-bind-%D9%88-this-%D8%AF%D8%B1-javascript-%D9%88-react-%D8%A8%D8%A7%DB%8C%D8%AF-%D8%A8%D8%AF%D9%88%D9%86%DB%8C%D9%85-buagaclkgaxm</link>
                <description>مفهوم bind، از اون مواردیه که تازه‌کارها رو اذیت میکنه. تا حدی که ممکنه دست از یاد گرفتنِ مفهوم اصلیش بردارن و فقط به استفاده با آزمون و خطا اکتفا کنند. توی این مقاله قراره با زبان خیلی خیلی ساده، این مفهوم رو خوب متوجه بشیم و بعد از اون اسامی مختلف bind رو یاد بگیریم و در آخر، سراغ علت استفادش توی class componentهای ری‌اکت بریم :))با این تیکه کدِ خیلی ساده شروع می‌کنیم.First Snippet: Implicit bindingکاملا مشخصه که خروجی این تیکه کد، 27 میشه. تا اینجا همه چی خوب پیش میره و مشکلی وجود نداره. اما مشکل از جایی شروع میشه که این function رو توی یه متغیر بریزیم. درمورد خروجی این تیکه کد خوب فکر کنین و تا قبل اون، مقاله رو ادامه ندین:Second Snippet: Default Bindingاین تیکه کد، بهمون undefined برمیگردونه! تنها تفاوتش هم با حالت قبلی اینه که فانکشنمون رو توی یه variable ریختیم.فرض کنین با ریختن این فانکشن توی متغیر age، این اتفاق میفته:Third Snippet: Default Bindingمیدونین this توی کد بالا داره به کجا اشاره میکنه؟ برای فهمیدن این موضوع من توی فانکشن showAge، از لاگ، this.age رو به this تبدیل میکنم. یعنی:showAge: function () {
     console.log(this);
}با این تغییر، اگر توی Node.js باشیم، global و اگر توی محیط browser باشیم، window بهمون برگردونده میشه.خب، تا اینجا منطقی شد که چرا undefined می‌خوریم. توی global و window چیزی به اسم age وجود نداره و this وقتی که توی variable ریخته میشه، دیگه به object خودش اشاره نمیکنه و میره سراغ global و window. اینجاست که bind به کمکمون میاد که به این variable بفهمونیم this باید به کجا اشاره کنه و وصلش کنیم به هرجا که میخوایم! پس کد نهایی ما به این شکل میشه:Fourth Snippet: Explicit Hard Bindingاما میخوایم عمیق‌تر بشیم :) فرض کنین به جای یک آبجکت userData، دو تا آبجکت داشته باشیم، و میخوایم هر موقع که دوست داشته باشیم متغیرمون رو به یکی از این آبجکت‌ها bind کنیم. این تیکه کد رو خوب نگاه کنین:Fifth Snippet: Explicit Hard Bindingپس توی اینجا می‌بینید که به راحتی می‌تونیم به هرکجا که دوست داریم، bind کنیم.و اما میخوایم حالتای بالا رو دسته‌بندی کنیم. اگر دقت کنین زیر همه عکسا یه سری اسم نوشتم. بریم ببینیم معنی هرکدوم چیه :)1. Default Bindingهمونجور که از اسمش مشخصه، حالتیه که ما bind نمیکنیم و this به همون حالت default اشاره میکنه. یه نکته خیلی خیلی مهم که جلوتر هم ازش استفاده میکنیم!اگر توی strict mode باشیم، default binding برای this، مقدار undefined داره.حالا اینجا میتونیم علت این رو بفهمیم که چرا اگه توی class componentهای React، یه فانکشنی رو صدا می‌زنیم، بعضی موقعا داره بهمون undefined میده! شاید براتون سوال باشه که خب من از strict mode استفاده نمی‌کنم. پس چرا توی class componentای که نوشتم، this داره undefined برمیگردونه؟!نکته باحال‌تری که وجود داره اینه:بدنه‌ی کلاس‌های JS، خود به خود توی strict mode اجرا میشن!علت این موضوعم برمیگرده به یه مشکلی که تا ECMAscript 262 edition 5 وجود داشت که واردش نمیشیم.پس به طور خلاصه:Default Binding in strict mode =&gt; undefinedOtherwise =&gt; global or windowبه اضافه این که کلاس‌ها به صورت دیفالت strict mode هستند. برای واضح‌تر شدن هم به تیکه کد دوم و سوم همین مقاله مراجعه کنین (زیر عکس‌ها عدد و نوع binding وجود داره حتما بررسیش کنید). بریم برا حالت بعدی :)2. Implicit bindingهمین حالتی که بحثش رو اول مقاله کردیم. یعنی وقتی که this خود به خود به جای دیگه غیر از default binding اشاره کنه. حالا با این اسم‌ها خیلی راحت‌تر میتونیم این نکته رو بگیم و بحثای اول مقاله رو جمع‌بندی کنیم:اگر یک فانکشن از داخل object رو توی variable بریزیم، از حالت Implicit binding به Default Binding تبدیل میشه. و برای همین this.age توی عکسای بالا، undefined میخوره. چون توی global و window چیزی به اسم age وجود نداره.برای این که دقیق‌تر متوجه نکته‌ی بالا بشین، پیشنهاد میکنم یه بار دیگه اولین تیکه کد مقاله رو ببینین.3. Explicit Hard Bindingترکیب مورد 1 و 2! یعنی وقتی که مثل نکته بالا، Implicit binding به Default Binding تبدیل بشه و ما بخوایم به همون آبجکت برگردونیمش. و همون اتفاقایی که بالا دیدیم که به هرجا که دوست داشتیم bind میکردیم. مثالشم میشه تیکه کد چهارم و پنجم همین مقاله :)و اما اتفاقی که توی class componentهای React میفتهمی‌رسیم به جای جالب ماجرا!برای خیلیامون سواله که وقتی داریم توی یه ایونتی، از یه فانکشن استفاده می‌کنیم، کِی باید از bind استفاده کنیم. اونایی که مفهوم رو یاد نگرفتن میبینن که بعضی موقعا بدون bind داره کار میکنه و بعضی موقعا ارور میده! توی این قسمت همه این موارد رو بررسی میکنیم? با این تیکه کد شروع میکنیم. برای خیلیامون این تیکه آشناست. اما میدونین چرا توی این حالت undefined میخوریم؟توی تیکه کد بالا میخوایم یه اسمی که از propهای component اومده رو alert کنیم. و مشخصاً به thisای احتیاج داریم که Implicitly Bound یا Explicitly Hard Bound باشه نه default bound (سعی کنین اسما رو برا خودتون تکرار کنین که حالتای مختلف bind رو بدونین.و اما نکته مهم ماجرا که چرا undefined میخوریم و thisامون default bound هست؟ وقتی داریم از eventها استفاده میکنیم، فانکشن event handler که توی تیکه کد بالا alertNameعه، Implicit Binding خودش رو از دست میده و به Default Binding برمیگرده.ممکنه بازم بگین خب اوکی :)) Implicit binding چرا تبدیل به default binding میشه؟! باید در جواب بگم که شما کل ماجرا رو اینجور در نظر بگیرین.let click = this.alertName;
click();اگه بخوایم فنی‌تر به قضیه نگاه کنیم، کلیت حرفم اینه که ما یه event handler (که توی اینجا فانکشن alertName هست) رو می‌خوایم به ایونت  بدیم. دقیقا این اتفاق نمیفته ولی شبیه‌سازی از همون موضوعه. پس رسیدیم به حرف اول مقاله که یه چیزِ thisدار رو ریختیم توی یه variable و از حالت implicit بردیمش به default. و اکثر موقعا توی constructor میایم کار bind رو انجام میدیم یا بعضی موقعا توی همونجا که داریم event handler رو صدا میزنیم. و اما سوال دیگه‌ای که پیش میاد:چرا توی constructor این کار رو انجام میدیم؟میخوایم مثال بالا رو ادامه بدیم تا از مقدار undefined برای this، خارج بشیم. این تیکه کد برای هممون آشناست:constructor(props) {
    super(props);
    this.alertName = this.alertName.bind(this);
}اما بیاید جدا جدا این خط رو با شناخت الانمون از bind انجام بدیم. اول از همه توی constructor از this لاگ میگیریم:constructor(props) {
    super(props);
    console.log(this);
}چیزی که تو کنسول بهمون نشون میده، کل کامپوننتمونه که طبق مثال اسم کامپوننتمون Login هست. حالا اگر this.alertName رو لاگ بگیریم، خود فانکشن رو بهمون نشون میده. یعنی چیزی که توی کنسول میبینیم میشه:ƒ alertName() {
    alert&#40;this.props.name&#41;;
}خب، پس تا الان خود فانکشنمون رو سمت چپ این خط کد داریم:    this.alertName = this.alertName.bind(this)و دقیقا داریم Explicit Hard Binding رو اینجا انجام میدیم! یعنی this(که قبل‌تر لاگ گرفتیم و بهمون خود کامپوننت رو داد) رو به فانکشنمون که this.alertName هست، bind میکنیم که thisهای توی فانکشن، به جای اشاره به undefined، به خود کلاس Login اشاره کنند و اینجاست که میتونیم از this.props استفاده کنیم :)خیلی سخت بهش نگاه میکردیم نه؟! به همین سادگی این موضوع که برای هممون توی React سوال بوده، واضح میشه.پایان سختی‌ها با Arrow Functions!اینجا والت در نقش arrow functionعه و اسکایلر اونور خط، bindعه?و اما اسم‌گذاری آخر برای bind! تا حالا سه نوع Default Binding و Implicit binding و Explicit Hard Binding رو گفتیم. میمونه نوع آخر که قراره تقدیم arrow functionهای عزیز کنیم.4. Lexical bindingاگر از Arrow Functionها استفاده کنیم، دیگه نیاز به هیچ نوع bindای نداریم. چون به صورت اتوماتیک خودشون this رو به اسکوپی که تعریف میشن bind میکنن :)))خیلی کوتاه و جامع و مفید: Arrow Functionها کلا از این مسخره‌بازیای bind خوششون نمیاد!پس حالا میتونیم علت اون &quot;بعضی موقعا کار میکنه&quot; توی ری‌اکت رو بفهمیم.مثلا می‌تونیم همونجا که فانکشن alertName رو صدا می‌زنیم، از arrow function استفاده کنیم:یا این که میتونیم این تیکه  رو مثل قبل نگه داریم، ولی بالا رو به صورت Arrow function بنویسیم. یعنی:یکی از تفاوتای function با arrow function که توی سوالات مصاحبه زیاد پرسیده میشه هم اینجا مشخص میشه. قابلیت Lexical binding!سخت نبود نه؟ این فقط یه مثال بود از همه چیزایی که ممکنه پیگیریشون نکرده باشیم. و ممکنه یکی از همین موارد توی پروژه‌های بزرگ، مشکلات بزرگ ایجاد کنند و توی بدترین مواقعِ ممکن باعث دردسر بشن! توی این چند مقاله اخیر سعی کردم چندتا از این مثال‌‌های skipشده رو بیارم. مثل asynchronous و package-lock و ... . امیدوارم که براتون مفید بوده باشه :)موفق و سربلند باشید❤Reza Hasani</description>
                <category>Reza Hasani</category>
                <author>Reza Hasani</author>
                <pubDate>Sat, 24 Oct 2020 21:47:52 +0330</pubDate>
            </item>
                    <item>
                <title>یک بار برای همیشه asynchronous را یاد بگیریم!</title>
                <link>https://virgool.io/jshints/asynchronous-hc3fiw21xyrj</link>
                <description>یکی از مواردی که تازه‌کارهای برنامه‌نویسی بهش برمیخورن، اصطلاح asynchronous هست. اصطلاحی که ممکنه توی دید اول خیلی واضح نباشه و وقتی کار به syntax و ... میرسه اوضاع پیچیده‌تر میشه. توی این مقاله اول قراره یکی از این syntaxها رو خیلی سریع بررسی کنیم و بعد از اون، سراغ قسمت اصلی مقاله یعنی تمام اتفاقای جذابی که موقع استفاده از asynchronous رخ میده خواهیم رفت.با این تیکه کد شروع میکنیم تا یه Promise ساده دریافت کنیم. احتمالا بدونین که تابع async همیشه بدون استثنا Promise برمیگردونه. یعنی باید منتظر یه اتفاقی بمونه. اون اتفاق میتونه response با کد 200 باشه یا ارور یا اتمام یه تایمر یا کلا هرچیز دیگه‌ای که باید براش منتظر بمونیم.و اما کلمه کلیدی await: قبل از هرچیزی لازمه این نکته رو به خاطر بسپارین که کلمه کلیدی await فقط و فقط در توابع async قابل استفاده‌ست. نه هیچ جای دیگه! این تیکه کد رو خوب نگاه کنین:پس await توی تیکه کد بالا صبر میکنه تا نتیجه مورد نظرمون دریافت بشه. یه نکته خیلی مهم رو دقت کنین که await نمیاد CPU رو به خاطر این قضیه درگیر کنه و کلا همه کارا رو متوقف کنه تا جواب بهش برگردونده بشه بلکه بقیه کارا همزمان انجام میشن. اثبات این موضوعم توی ادامه مقاله قراره انجام بدیم?و اما قسمت جذاب ماجراتا حالا به این موضوع فکر کردین که وقتی دارین از توابع asynchronous استفاده میکنین، چه اتفاقی داره رخ میده؟ اصلا به درد میخوره یاد بگیریم؟ شکککک نکنین توی خیلی از رفع باگ‌ها کمک میکنه و فرشته نجات میشه! پس قراره باهم یاد بگیریمش :)قبل از شروع بحثمون، دو تا اصطلاح رو باید معرفی کنم. دوتا اصطلاحی که خیلیامون توی inspect مرورگرامون دیدیم، اما معنیشو نمی‌دونیم:Call Stack    |    2. Callback Queueبا یه کد ساده شروع میکنیم و کم‌کم به سمت asynchronous پیش میریم.یادتون باشه اگر از asynchronous استفاده نکنیم، از مورد دومی یعنی Callback Queue هم استفاده نکردیم.اولین مثالمون asynchronous نیست و یه تابع عادیه. پس طبق نکته بالا از Callback Queue استفاده‌ای نمیشه. میخوایم ببینیم چه اتفاقی توی Call Stack داره رخ میده:یه تیکه کد خیلی ساده!خب بریم سراغ Call Stack برای این تیکه کد. هرکدوم از pushها رو توی موارد جداگونه و به صورت boldشده اوردم:1- اولین چیزی که داخل این استک push میشه، تابعیه به اسم «main». دقیقا شبیه ++C که همچین تابعی رو به عنوان بدنه و فانکشن اصلی میشناخت ولی اینجا از نوع پنهان‌شدش? main پوش میشه.2- خط به خط جلو میره تا خط آخر یعنی جایی که تابع «testCallStack» صدا زده شده. توی استک روی main، این تابع push میشه.3- وارد testCallStack میشه. به تابع «forEach» میرسه. صداش میزنه و داخل استک روی main و testCallStack  پوش میکنه.4- داخل تابع forEach، از anonymous function استفاده شده. پس یه همچین چیزی داخل استک پوش میشه:anonymous(&#x27;Reza&#x27;)  &lt;- اولین رشته‌ای که دریافت میکنه5- و آخرین چیزی که بهش میرسه رو داخل کنسول چاپ و داخل استک push میکنه. یعنی:console.log(&#x27;Reza&#x27;)دو مورد آخری یعنی مورد 4 و 5، pop میشن و دوباره همین مراحل برای string بعدی آرایه تکرار و push میشه. و در آخر همه این موارد به ترتیب pop میشن و Call Stack خالی میشه.و اما برای توابع asynchronous چه اتفاقایی رخ میده؟میرسیم به قول اول مقاله... وقتی از asynchronous استفاده میکنیم دقیقا چه اتفاقایی داره میفته؟ تیکه کد خیلی ساده زیر رو دقیق بررسی کنیم تا همه چیزا برامون روشن بشه:قبل این که بخوایم بررسی کنیم، بد نیست روی خروجی یه مقداری فکر کنین و جلوتر جوابتون رو ارزیابی کنین. به نظرتون کدوم خروجی رو خواهیم داشت؟&#x27;I can not wait!&#x27; / &#x27;Zero seconds&#x27; / &#x27;I am done!&#x27; / &#x27;Two seconds&#x27; or&#x27;I can not wait!&#x27; / &#x27;I am done!&#x27; / &#x27;Zero seconds&#x27; / &#x27;Two seconds&#x27; or&#x27;I can not wait!&#x27; / &#x27;Two seconds&#x27; / &#x27;Zero seconds&#x27; / &#x27;I am done!&#x27;توی مثال ساده asynchronous بالا، میخوایم ببینیم چه اتفاقایی توی Call Stack و Callback Queue رخ میده. به ترتیب بررسی میکنیم و جلو میریم.مثل مثال قبلی، اولین چیزی که داخل Call Stack پوش میشه، تابع «main» هست. بعد از اون، باز هم طبق مثال قبل، console.log اولی، پوش و بعد از چاپ در کنسول، pop میشه. پس تا اینجای کار این خروجی‌ها رو توی کنسولمون داریم:&#x27;I can not wait!&#x27;و اما قسمت جذاب :)به console.log دومی میرسه. میبینه تایمر داره. اگر توی Call Stack پوش کنه، نمیتونه بعدا به این console.log برگرده. در لحظه هم که نمیتونه استفاده کنه و باید ۲ثانیه صبر کنه. طبق چیزی هم که اول مقاله گفتم، CPU این ۲ثانیه رو صبر نمیکنه و بقیه تسک‌ها رو همزمان باهاش انجام میده. پس فرشته نجات ما این وسط کیه؟قبل از این که بریم سراغ جواب سوال بالا، لازمه یه نکته خیلی مهم رو درمورد جاوا اسکریپت ذکر کنم که فرضیه کمک‌گرفتن CPU از هسته دیگه برای تسک‌های همزمان رو درجا باطل میکنه:جاوا اسکریپت فقط و فقط و فقط یک thread دارد!پس تا اینجای کار برامون قطعی شد که نمیتونیم اون تایمر رو توی Call Stack پوش کنیم که مثلا توی thread جداگونه بهش برسیم.این که CPU رو متوقف کنیم هم که معلومه کار درستی نیست! فکر کنین برای یه response از api اگر سرور دیر جواب میداد، هیچی توی صفحه وبمون نمایش داده نمیشد! درحالی که میدونیم اینجور نیست :)پس چه شگردی به کار برده شده تا بدون استفاده از thread و توقف CPU، تسک‌های بعدی مثل ساعت کار کنن؟جواب: APIهای نوشته شده براِی نود جی‌اس + Callback Queueاما چه جوری؟ برمیگردیم به مراحلی که داشتیم دونه به دونه میرفتیم. وقتی به خط کد console.log دومی میرسیم، این تیکه کد داخل APIهای Node موقتا نگه‌داری میشه و تایمر ۲ثانیه‌ای توی اونجا براش شروع به شمارش میکنه. پس تا الان Call Stack خالیه و جا برای تسک‌های بعدی داریم.سراغ console.log سومی میره( همزمان عکس کد رو هم ببینین). دوباره وارد APIهای Node میشه و تایمر 0ثانیه‌ای براش گذاشته میشه. و همچنان Call Stack خالی :)))تایمر 0ثانیه برای console.log سومی تموم شد! اینجا نقش آخر داستان وارد میشه! Callback Queue?مثلا Callback Queueعه?لاگ سومیمون که تایمر 0ثانیه داشت، الان دیگه توی APIها نیست و این مورد زیر، وارد Callback Queue میشه:Callback (0sec)میره سراغ console.log آخری. تایمر نداره پس API و Callback Queue در کار نیست و فقط داخل Call Stack پوش، چاپ و سپس pop میشه. پس کنسولمون تا اینجای کار میشه:&#x27;I can not wait!&#x27; / &#x27;I am done!&#x27;نکته جالب اینجاست. حتی main که اون اولین push هم بود pop میشه! و Call Stack خالی خالی میشه! حالا Callback Queue میبینه Call Stack خالیه و اینجاست که ابتدا (Callback (0sec و بعد از اون console.log سومی رو برای Call Stack میفرسته و به ترتیب push و pop میشن:&#x27;I can not wait!&#x27; / &#x27;I am done!&#x27; / &#x27;Zero seconds&#x27;همه این اتفاقا، زیر ۲ثانیه رخ داده! همشون توی زمان ۰ مطلق اتفاق افتاده. بعد از ۲ثانیه، از APIهای Node، لاگ دومی وارد Callback Queue میشه. پس مثل قبلی، همچین چیزی وارد Callback Queue میشه:Callback (2sec)دوباره Callback Queue میاد داخل Call Stack رو چک میکنه و میبینه خالیه. پس وقتشه که مثل قبلی اون دومورد (Callback (2sec و console.log رو push و سپس pop کنه.یعنی خروجی‌ها به ترتیب اینجوری میشن(گزینه دوم تست بالا):&#x27;I can not wait!&#x27; / &#x27;I am done!&#x27; / &#x27;Zero seconds&#x27; / &#x27;Two seconds&#x27;جمع‌بندییه جورایی میتونیم اینطور در نظر بگیریم که Callback Queue واسطه‌ایه بین APIهای Node و Call Stack. به این صورت که (Callback (nSec بعد از تموم‌شدن تایمر nثانیه، از طرف APIهای Node برای Callback Queue فرستاده میشه. توی Callback Queue چک میشه که آیا Call Stack خالی هست یا نه(حتی main هم نباید توی استک باشه). اگر خالی بود از صف dequeue میشه و داخل Call Stack پوش میشه.صف صبحگاهی مدرسه رو در نظر بگیرین. بعد از اتمام مراسم صبحگاهی(تموم‌شدن تایمر nثانیه) و وقتی که دانش‌آموزا میخوان وارد کلاس بشن، ناظم مدرسه(Callback Queue) میاد کوتاهی ناخن دانش‌آموزاش(خالی بودن Call Stack) رو چک میکنه. اگه کوتاه(خالی) بود اجازه میده که وارد کلاس(Call Stack) بشن. اگه نه صبر میکنه تا تعهد بدن(Call Stack خالی بشه). کاملا واضح شد دیگه فکر کنم?همین مورد که 2ثانیه و 0ثانیه طول کشید، میتونه یه request به API باشه. پس یادتون باشه که دقیقا همین اتفاقا میفته وقتی ما درخواستی رو ارسال میکنیم و منتظر response میمونیم.کنجکاو باشیم!دنبال همه چیز باشیم! هیچ یادگیری‌ای رو حتی برای کوتاه مدت، پشت گوش نندازیم. چون خیلی زود خودشو نشون میده و ممکنه اون تایم برای یادگیری خیلی دیر باشه.همین مورد Call Stack ممکنه چیزی باشه که خیلیا بگن اون پشت داره اتفاق میفته و ما نمیبینیم پس به چه درد ما میخوره؟ در جواب باید گفت که همین ترتیب اجرای چند تیکه کد، میتونه باعث کشف یه باگ بزرگ توی پروژه بشه که هرکسی از پس اون برنمیاد.آرزو میکنم شما اون فردی باشید که از پسش برمیاین?موفق و سربلند باشید❤Reza Hasani</description>
                <category>Reza Hasani</category>
                <author>Reza Hasani</author>
                <pubDate>Sat, 01 Aug 2020 00:24:25 +0430</pubDate>
            </item>
                    <item>
                <title>چرا باید package-lock.json را دوست داشته باشیم؟!</title>
                <link>https://virgool.io/jshints/package-lockjson-%DB%8C%D8%A7-packagejson-qm9andwubmt3</link>
                <description>اکثر ما توی محیط‌های کاری مختلف، به افرادی برخوردیم که بیشتر از ما توی یه سری چیزا کنجکاو میشن و میخوان علت وجود هرچیزی رو بدونن. ممکنه پیش خودمون سوال کرده باشیم که واقعا ریز شدن توی این موارد کمکی هم میکنه یا نه؟?وقتی که وسط یه پروژه کامپوننت‌ها سنگین شد و کم‌کم به مشکلاتی به ظاهر غیرمنطقی برخوردم، متوجه شدم که جواب سوال بالا، آره هست!یکی از این موارد، این دوتا فایلیه که هممون دیدیمش(package.json و package-lock.json). فایلایی که فقط ممکنه در حد گذاشتن یا نگذاشتن توی gitignore و یه سری لیست dependency ازشون بدونیم. توی این پست کاربرد و تفاوت‌های این دوتا فایل رو قراره یاد بگیریم.package-lock.jsonقبل از شروع بحثمون، یه سوالی رو مطرح میکنم.چرا package-lock.json حتما و حتما و حتما باید توی source control و commitهامون وجود داشته باشه؟ تا حالا راجع بهش فکر کردین؟ جواب این سوالو آخر این مقاله متوجه خواهید شد :))تا قبل از ورژن 5 npm، فایلی با عنوان package-lock.json بعد از زدن دستور npm install تولید نمیشد و تا اون موقع از package.json برای نصب ماژول‌ها توی سیستم شخص دیگه استفاده میشد. اما از بعد این ورژن، فایل package-lock.json اطلاعات خیلی بیشتری رو درمورد هر پکیج و dependencyهای اون پکیج بهمون میداد. و این یعنی به صفر رسوندن اختلاف برای نصب ماژول‌ها توی سیستم شخص دیگه :) پس برعکس چیزی که هممون فکر میکنیم، npm برای نصب پکیج‌ها، از package.json یک لیست dependency پیدا میکنه و برای ورژن پکیج‌های اون لیست، سراغ package-lock.json میره( بد نیست توی پرانتز اشاره کنم که دستور npm ci، برعکس npm i مستقیما به package-lock.json نگاه میکنه و از package.json فقط برای بررسی هماهنگی بین ورژن‌های دو فایل استفاده میکنه. و اگه ورژن‌های یک پکیج در این دو فایل یکی نبودند، موقع نصب ارور میده )ممکنه الان توی ذهنتون بیاد که package.json برای نصب یک ماژول کافیه چون دقیقا ورژنی که میخوایم رو داره و وقتی یه کاربری npm install میزنه و توی لیست dependencyها ورژن دقیق یک ماژول رو داشته باشیم، دقیقا مثل اینه که زده باشیم npm install sth@v.v.v. پس چرا package-lock.json نیاز داریم؟جواب: dependencies of dependency :)با مثال توضیح میدم. فرض کنید میخوایم پکیج react-helmet رو توی ورژن 5.2.1 نصب کنیم. دستور زیر رو میزنیم.npm i react-helmet@5.2.1بلافاصله بعد از نصب، فایل package-lock.json هم آپدیت میشه. از طرفی هم توی package.json این خط به dependencies اضافه خواهد شد:&amp;quotdependencies&amp;quot: {
    &amp;quotreact-helmet&amp;quot: &amp;quot^5.2.1&amp;quot
}مشکل دقیقا از اینجا شروع میشه! توضیحات package.json برای یک پکیج کافی نیست! خود react-helmet قطعا dependencyهایی داره که هرکدومشون ورژن خاصی دارن. وقتی که ورژن react-helmet تغییری نکرده و همون 5.2.1 باقی مونده ولی کاربرِ دیگه پروژه رو میگیره و npm i میزنه، ممکنه ورژن چندتا از dependencyهایی که react-helmet استفاده کرده تغییر کرده باشه! چیزی که به هیچ وجه توی package.json وجود نداره. و باگ از جایی شروع میشه که اون تفاوت ورژن dependency، باعث بشه یک سری فانکشن‌ها به شکل دیگه عمل کنند! و اینجاست که متوجه حرف اول مقاله میشیم! فکر میکنیم غیر منطقیه! ولی مشکل از ما بوده که package-lock.json رو فایل اضافی تلقی میکردیم و اون رو توی gitignore گذاشتیم :))با هم اجزای موجود توی فایل package-lock.json برای مثالی که زدیم رو بررسی میکنیم:محتویات package-lock برای react-helemt@5.2.1ورژن پکیج‌هایی که react-helmet داره از اونا استفاده میکنه رو به خوبی توی عکس بالا میبینید. پس npm برای نصب ماژول‌ها از این فایل استفاده میکنه چون هرچیزی که مورد نیازشه دقیقا توی این فایل ذکر شده. اگر دوست داشتین بیشتر درمورد integrity و تفاوت sha512 , sha1, ... بدونین، این document رو پیشنهاد میکنم https://w3c.github.io/webappsec-subresource-integrity/Semantic Versioningتوی این قسمت میخوام درمورد ورژن‌بندی npm هم موردی رو ذکر کنم. اگر دقت کرده باشید ورژن‌های همه پکیج‌های npm یا ورژن پروژه خودتون موقع زدن دستور npm init، از سه عدد تشکیل شده که به صورت a.b.c هست. به این روشی که npm استفاده میکنه، semantic versioning یا به اختصار semver میگن. که توی این روش ورژن بندی هرکدوم از حروف a, b, c، نشان‌دهنده یه نوع تغییر هستند که به صورت زیر هست:a.b.c -&gt; a: major version, b: minor version, c: patch versionsآخرین حرف یعنی c، نشان‌دهنده یک bugfix هست که تغییر بزرگی رو توی پکیج ایجاد نکرده.دومین حرف یعنی b، نشان‌دهنده یک سری تغییر در فانکشن‌ها و عملکردهای پکیج هست که باز هم این تغییر باعث تغییر بزرگ توی پکیج و عوض شدن کلیِ چیزها نمیشه.و اما اولین حرف یعنی a، نشان‌دهنده تغییر بزرگیه که ممکنه روی پروژه‌ای که ما ازش استفاده میکنیم ناهماهنگی‌هایی رو به وجود بیاره. پس اگر a توی پکیجاتون فرق کرد، احتمالا مجبورید که برای یک سری جاها document اون پکیج رو دوباره مطالعه کنید?حالا فرض کنید یکی از dependencyهای پکیج react-helmet، از 15.5.4 تبدیل بشه به 16.5.4 و فایل package-lock توی source control وجود نداشته باشه. همه اعضای تیم بعد از باگ:همه این‌ها گفته شد تا به یک نتیجه برسیم:وجود package-lock.json در source control اجباریست و تنها دلیل آن هم dependencyهای پکیجیست که نصب کردیم.و سخن آخر این که سعی کنیم شبیه اون آدمای کنجکاو باشیم! وگرنه مشکلاتی ممکنه برامون پیش بیاد که تا مرز توقف پروژه برای یه تایم طولانی پیش بره.موفق و سربلند باشید❤ Reza Hasani</description>
                <category>Reza Hasani</category>
                <author>Reza Hasani</author>
                <pubDate>Sun, 12 Jul 2020 19:37:48 +0430</pubDate>
            </item>
                    <item>
                <title>مفهوم IIFE و Closure در جاوا اسکریپت و Nested Functions</title>
                <link>https://virgool.io/jshints/%D9%85%D9%81%D9%87%D9%88%D9%85-iife-%D9%88-closure-%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-%D9%88-nested-functions-t4ydsgkij1vg</link>
                <description>جاوا اسکریپت پره از ارورهایی که خیلی موقعا دردسرای بزرگی رو توی پروژه‌ها ایجاد میکنه. اما یه سری قوانین میتونن به کمکمون بیان تا به جای handle اون ارور با روش‌های غیر منطقی و کد کثیف، خیلی راحت درک و از ریشه حلشون کنیم. توی این پست میخوایم یکی از اون مشکلات و روش handleش رو یاد بگیریم :)خیلی وقتا نیاز داریم که توی functionمون، یه function دیگه داشته ‌باشیم تا بتونیم از دیتاهای موجود استفاده کنیم. روش خیلی خوبیه برای این که سمت تعریف متغیر global یا setState و ... نریم. اما ممکنه این کارمون منجر به ارورهایی بشه که توی این متن با این ارورها و handleکردنشون آشنا میشیم!اول کار رو با یه مثال شروع می‌کنم. به نظرتون با call کردن تابع f، چه خروجی‌ای خواهیم‌داشت؟ (قبل از خوندن ادامه متن، حتما روش فکر کنین)خروجی f به نظر شما چیه؟جواب: undefined!و اما علتش چیزی میشه که ما رو میرسونه به مفهوم خیلی مهمی به اسم Closure. نقل قول زیر میتونه درجه اهمیتش رو برسونه:Coding in JavaScript without an understanding of closures is like trying to speak English without an understanding of grammar rulesاگر بخوام خیلی کوتاه و ساده تعریف کنم، باید بگم که closureها هستن که به ما اجازه دسترسی از inner function به outer function میدن. این رو هم یادتون باشه که توی JavaScript، بلافاصله بعد از ساخته‌شدن تابع، closure هم ساخته میشه.توی تیکه کد بالا، وقتی وارد scope توی function اصلی(wrapElements) میشیم، برای هر variable که result و i و n هستند، یه slot توی memory اختصاص داده میشه (allocate)و مشکل از جایی شروع میشه که ما وارد حلقه for میشیم. وقتی وارد این حلقه میشیم، خیلیامون انتظار داریم که خود value از i رو داشته‌باشیم. در حالی که ما فقط و فقط یک reference از i داریم و دیگر هیچ!پس یادمون باشه که:Closures store their outer variables by reference, not by valueعلت undefinedگرفتنمون حالا معلوم میشه: این که functionهای داخلی، منتظر میمونن تا آخرین مقدار Closure براشون فرستاده بشه. یعنی توی این تیکه کد، توی حلقه for، تابع صدا زده نمیشه تا وقتی که i به عدد 5 که مقدار نهایی هست میرسه. و اینجاست که میخواد توی آرایه با ایندکس‌های 0 تا 4، دنبال ایندکس 5 بگرده و به undefined میخوره :)حالا فرض کنید var i رو اون بالا تعریف نکنیم و بیاریمش تو scope پایینی و همونجایی که قراره استفادش کنیم. پس کد ما این شکلی میشه:جالبه بدونید که اینجا هم undefined میخوریم!و علتش هم اینه که وقتی ما توی scopeهای پایینی، متغیری رو تعریف می‌کنیم، دقیقا مثل اینه که اون بالا تعریفش کردیم و این پایین ازش استفاده میکنیم! پس بار دیگه، فقط و فقط یه slot توی مموری برای i خواهیم داشت. دقیقا مثل تیکه کد اولمون.پس با ارور آشنا شدیم :) چجوری هندلش کنیم؟جوابش ما رو میرسونه به عنوان بحثمون یعنی Immediately Invoked Function Expressionاین تیکه کد رو خوب نگاه کنید!استفاده از تکنیک IIFEاین تکنیک توی هر تغییر i، یه function میسازه و بلافاصله صداش میزنه. و اینجاست که آرایه result با هر تغییر i، یه عضو جدید درست میکنه. خوبه که اسم اصلی اینجور تعریف توابع رو هم بدونیم: Self-invoking functions و دیگه ارور undefined رو نخواهیم‌ داشت?پس به همین راحتی و با خوندن چند کتاب خوب از جاوا اسکریپت، میتونیم این مشکلا رو از ریشه متوجه بشیم تا این ارورها و handleکردن غیرمنطقیشون، بعدا باعث شکل‌گیری فاجعه توی پروژه نشهموفق و سربلند باشید❤ Reza Hasani</description>
                <category>Reza Hasani</category>
                <author>Reza Hasani</author>
                <pubDate>Wed, 01 Jul 2020 01:08:37 +0430</pubDate>
            </item>
                    <item>
                <title>فاجعه کد کثیف!</title>
                <link>https://virgool.io/@reza.hasani7899/%D9%81%D8%A7%D8%AC%D8%B9%D9%87-%DA%A9%D8%AF-%DA%A9%D8%AB%DB%8C%D9%81-kf9a9r1k6yoc</link>
                <description>داستان از یه مریضی، وسط یه پروژه سنگین شروع شد. دوهفته‌ای که نتونستم کار کنم و همکارم باید پروژه رو جلو می‌برد...و بعد از دوهفته‌ای که برگشتم و با وجود کلی تسک، هیچ تغییری تو کامپوننتای خودم ندیدم.چرا؟ چون کدا واضح نبودن و بعضی کامپوننتا به 700-800 خط کد میرسیدن :))) دقیقا همون موقع بود که تصمیم گرفتم راجع به Clean Code کتاب بخونم و تحقیق کنم. و اونجا بود که لذت کدزدن و معنای واقعی development رو درک کردم :)خیلیا میگن کد من تمیزه و مشکلی نداره و غیره و غیره... و واقعا توی خودشون نیازی به خوندن این قوانین نمی‌بینناگر کسی بدون توجه به قوانینی که ثابت شدست همچین حرفی بزنه، قطعا اشتباهه و احتمالا دود کد بد تو چشم همچین فردی نرفته!شاید چون هدف این افراد از کد زدن، فقط و فقط &quot;پیاده‌سازی&quot; هست و وقتی به این مرحله برسن، شاد و خندان وارد تیکه‌های بعدی پروژه میشن در حالی که نمیدونن تو آینده نزدیک، قراره چه اوضاعی پیش بیاد?برای همچین تفکری، یه نقل قول معروف از Martin Fowler داریم که میگه:Any fool can write code that a computer can understand. Good programmers write code that humans can understand.می‌دونستی اگه if, else, while تو کدات، بیشتر از یه خط باشه، باعث بی‌نظمی شده؟می‌دونستی اگه فانکشنت بیشتر از 20خطه، یعنی از قوانین clean code پیروی نکردی؟میدونستی 90-95درصد کامنتایی که وسط پروژت داری، فقط و فقط کداتو شلوغ کرده؟میدونستی فانکشنی که بیشتر از یه کار انجام بده، از اساس غلطه؟ (مثلا فکر کن یه کامپوننت توی فرانت‌اند دستت داری که عمل لایک رو انجام میده. حالا وقتی روی لایکه کلیک شد، تو فانکشنت هم بیای UI رو عوض کنی و یه دونه به تعداد لایکا اضافه کنی، و هم بیای و به API ریکوئست بزنی... غلطه?) پس اگه فانکشنت داره تو argumentها، flag میگیره، شک نکن اون تیکه کد تمیز نیست! چون داره دوتا کار انجام میده و باید به دوتا فانکشن تبدیل شه!میدونستی اگه فانکشنت بیشتر از دوتا argument میگیره، باعث گیجی خواننده کدات میشه؟ حتی خود دوتا argument هم شرط و شروط داره?میدونستی اگه یه تیکه از کدتو داری کپی میکنی که با تغییر یه قسمتیش، دوباره استفادش کنی، احتمال زیاد داری اشتباه میزنی؟Duplication may be the root of all evil in softwareو کلی میدونستی‌های دیگه که اگر این پست ری‌اکشن خوبی بگیره، براتون جدا جدا مینویسمشون :))یه نکته خیلی خیلی مهم!قرار نیست حکایت اون کلاغه باشیم که اومد راه‌رفتن کبک رو یاد بگیره، راه‌رفتن خودشم یادش رفت!قراره هررر سبکی که برا کدزدن داریم رو دقیقا به همون شکل حفظ کنیم. فقط و فقط اولش روی &quot;اجرا کردن&quot; عملکرد مورد نظرمون تمرکز می‌کنیم... دقیقا مثل قبل!نوشتن کد شبیه نوشتن مقاله‌ست!اصلا بیا دو دیقه از بحث کد جدا بشیم و فرض کنیم می‌خوایم مقاله بنویسیماولین کاری که میکنی اینه که هرچی از ذهنت بیرون میاد رو می‌نویسی.چیزی که تو ذهنت بود رو تو مقاله اوردی؟ حالا وقت ویرایش مقاله‌ست!وقت حاشیه خوشگل دادن و اصلاح جمله‌های طولانی و علائم نگارشی و غیره و غیره‌ستیه بار دیگه تیکه بالا رو بخون و این بار به جای مقاله‌نویسی فکر کن داری کد میزنیبه همین سادگی و با هزینه زمانی خیلی کمولی نجات‌دهنده!به درد خودمونم میخوره؟شککک نکن!تا حالا چندبار برات اتفاق افتاده تو کدای خودتم گم بشی؟و انقدددر فانکشنا تو هم تو هم بشه که برای پیدا کردن یه فانکشن ساده، کلی اسکرول کنی و به خاطر اسم variableها (که اگه فرصت شد تو پستای بعدی کامل توضیح میدمشون)، حتی با سرچ هم نتونی پیداش کنی؟کافیه 3-4 هفته بگذره و بخوایم به کدامون برگردیمخودمونم متوجه نمیشیم! حالا فکر کن یکی دیگه میخواد اونا رو بخونه و توسعه‌شون بده?و اگر بخواد بعد از مدتی به اون تیکه کد feature اضافه بشه یا چیزیش تغییر کنه، واقعا فاجعه ایجاد میشه!ما قراره کدی بزنیم که حتی کسی که 4ماه از hello worldش میگذره، وقتی به کدای پروژمون نگاه میکنه، بفهمه قضیه از چه قراره، حتی اگه تخصصی باشنقوانین خیلی راحتن و زمان زیادی ازت نمی‌گیرنبه امید تمیزی کدامون :)</description>
                <category>Reza Hasani</category>
                <author>Reza Hasani</author>
                <pubDate>Wed, 08 Apr 2020 23:00:49 +0430</pubDate>
            </item>
            </channel>
</rss>