قطعا همگی با Template Engine هایی مثل Pug, Handlebars و EJS آشنایی دارید. هرکسی با توجه به سلیقه ای که داره از یکی از اینها استفاده میکنه. من خودم استایل EJS رو به دلیل سادگی و نزدیک بودن به خود #JavaScript خیلی دوست دارم. حالا یک Template Engine جدیدتر داریم به اسم ETA که شباهت خیلی زیادی به EJS داره و با #Deno و #Browser هم سازگار هست و البته حجم کمتری داره و از EJS هم سریعتر هست.
اگر دوست دارید میتونید یک نگاهی بهش بندازید.
https://eta.js.org/
#NodeJS
اگر دوست دارید میتونید یک نگاهی بهش بندازید.
https://eta.js.org/
#NodeJS
👍18
Node Master
#Update #News
امروز آپدیت جدید برای #BunJS یعنی 1.1 منتشر شد. بزرگترین خبر مربوط به این آپدیت اضافه شدن ساپورت برای #Windows هست. کلی ویژگی های جدید دیگه بوده و کلی بهبود برای سازگاری بهتر با API مربوط به #NodeJS انجام گرفته.
درکل امسال قراره تابستون خیلی داغی 🔥 برای کامینیوتی #BackEnd و #JavaScript داشته باشیم باتوجه به این که #Deno داره خودش رو برای نسخه ۲ آماده میکنه و در یک ماه آینده ظاهرا باید انتظار منتشر شدن نسخه 22 LTS برای #NodeJS باشیم و ببینیم آیا میتونه #BunJS که مدعی این هست که جای #NodeJS در سال 2024 میخواد بگیره میرسه یا نه؟
https://twitter.com/bunjavascript/status/1732945030007099510
باتوجه به Drama های پیش اومده و کل کل بین runtime های مختلف شاهد رقابت خیلی سنگین تری بنظرم امسال هستیم به طوری که این رقابت داره تبدیل به مبارزه UFC میشه 🥊.
نظر شخصی :
به شخصه با #BunJS در حال حاظر حال نمیکنم به دلایل زیر
- سال گذشته حاشیه و Drama در کامینیوتی زیاد ایجاد شد و بخشیش از طرف #BunJS بود.
- هنوز بنظرم خیلی فاصله داره تا بگیم production ready هست. ( همه چیز سرعت نیست و stability بنظرم خیلی مهم تره )
این وسط #Deno میانه روی کرده و آروم و بی سر صدای اضافه خودش رو بهتر کرده و با حرکت آخرش یعنی jsr.io به نظر من خیلی جایگاه بهتری داره ( برای من ). تنها مشکلی که به نظرم داره کامینیوتی کوچیکش هست که برای پروژه زدن یکم کار رو سخت میکنه.
و این که #NodeJS که عنوان Rocket Turtle 🚀 🐢 رو یدک میکشه هم سال قبل با توجه به آپدیت هایی که داد به صورت جدی اعلام کرد که قصد نداره بازار رو به راحتی تسلیم کنه و کنار بکشه به طوری که به صورت مرتب شاهد improvement هستیم.
درکل امسال قراره تابستون خیلی داغی 🔥 برای کامینیوتی #BackEnd و #JavaScript داشته باشیم باتوجه به این که #Deno داره خودش رو برای نسخه ۲ آماده میکنه و در یک ماه آینده ظاهرا باید انتظار منتشر شدن نسخه 22 LTS برای #NodeJS باشیم و ببینیم آیا میتونه #BunJS که مدعی این هست که جای #NodeJS در سال 2024 میخواد بگیره میرسه یا نه؟
https://twitter.com/bunjavascript/status/1732945030007099510
باتوجه به Drama های پیش اومده و کل کل بین runtime های مختلف شاهد رقابت خیلی سنگین تری بنظرم امسال هستیم به طوری که این رقابت داره تبدیل به مبارزه UFC میشه 🥊.
نظر شخصی :
به شخصه با #BunJS در حال حاظر حال نمیکنم به دلایل زیر
- سال گذشته حاشیه و Drama در کامینیوتی زیاد ایجاد شد و بخشیش از طرف #BunJS بود.
- هنوز بنظرم خیلی فاصله داره تا بگیم production ready هست. ( همه چیز سرعت نیست و stability بنظرم خیلی مهم تره )
این وسط #Deno میانه روی کرده و آروم و بی سر صدای اضافه خودش رو بهتر کرده و با حرکت آخرش یعنی jsr.io به نظر من خیلی جایگاه بهتری داره ( برای من ). تنها مشکلی که به نظرم داره کامینیوتی کوچیکش هست که برای پروژه زدن یکم کار رو سخت میکنه.
و این که #NodeJS که عنوان Rocket Turtle 🚀 🐢 رو یدک میکشه هم سال قبل با توجه به آپدیت هایی که داد به صورت جدی اعلام کرد که قصد نداره بازار رو به راحتی تسلیم کنه و کنار بکشه به طوری که به صورت مرتب شاهد improvement هستیم.
X (formerly Twitter)
Bun (@bunjavascript) on X
We have one goal for 2024
Flip the default backend JavaScript runtime from Node.js to Bun
Flip the default backend JavaScript runtime from Node.js to Bun
👍23
همونطور که در عکس میبینید #CPP یک زبان Multi-paradigm هست. انجین اصلی #NodeJS و موتور #V8 که کار Parse کردن #JavaScript رو انجام میده در حقیقت یک برنامه پیچیده هستن که با #CPP نوشته شده. حالا این موضوع باعث ایجاد یکی از بزرگترین کنجکاوی ها برای من هست و هنوز جواب دقیق رو نمیدونم و فقط براساس حدس هست.
اگر یکم با زبان هایی مثل #C و #CPP کار کرده باشید مخصوصا C قشنگ با استایل procedural و imperative آشنا میشید. حالا اگر به #NodeJS نگاه کنیم که یک سیستم Event-Driven هست سوال برای ما ایجاد میکنه که چطور این تغییر و شیفت در نوع پارادایم ایجاد شده؟
بزارید ساده تر بگم یعنی چطور با استفاده از یک سیستم procedural یا imperative یا OOP یک سیستم Event-Driven طراحی میکنیم؟ به نظر من قطعا اینجا به نوعی با Observer pattern طرف هستیم ( که ظاهرا میشه همون Event-loop در js )
یک مثال ساده تر در توسعه #FrontEnd میبینیم. که از #JavaScript که imperative هست به سیستمی مثل #React رسیدیم که declarative هست.
درکل این شیفت بین پارادایم ها موضوع جالبی برای مطالعه هست و قسمت سخت سوال پیدا کردن خط مرزی بین اونا هست که چطور انجام میشه.
اگر یکم با زبان هایی مثل #C و #CPP کار کرده باشید مخصوصا C قشنگ با استایل procedural و imperative آشنا میشید. حالا اگر به #NodeJS نگاه کنیم که یک سیستم Event-Driven هست سوال برای ما ایجاد میکنه که چطور این تغییر و شیفت در نوع پارادایم ایجاد شده؟
بزارید ساده تر بگم یعنی چطور با استفاده از یک سیستم procedural یا imperative یا OOP یک سیستم Event-Driven طراحی میکنیم؟ به نظر من قطعا اینجا به نوعی با Observer pattern طرف هستیم ( که ظاهرا میشه همون Event-loop در js )
یک مثال ساده تر در توسعه #FrontEnd میبینیم. که از #JavaScript که imperative هست به سیستمی مثل #React رسیدیم که declarative هست.
درکل این شیفت بین پارادایم ها موضوع جالبی برای مطالعه هست و قسمت سخت سوال پیدا کردن خط مرزی بین اونا هست که چطور انجام میشه.
👍15
باتوجه به این که Array هم در #JavaScript یک Object هست کاملا این syntax درسته. یعنی فانکشن ما میتونه با استفاده از this اگر به عنوان یکی از index های array تعریف شده باشه به خود array اورجینال که در حقیقت یک object هست دسترسی داشته باشه.
این نکات رو بیشتر از زاویه fun fact یا عمیق تر شدن نگاه کنید. هیچ کد پروداکشنی پیدا نمیکنید این استایل کد ببینید.
const myArr = [
function myfn() {
console.log(this[1]);
},
2,
];
myArr[0]();
این نکات رو بیشتر از زاویه fun fact یا عمیق تر شدن نگاه کنید. هیچ کد پروداکشنی پیدا نمیکنید این استایل کد ببینید.
👍25
یکی از نکاتی که به برای بچه های #BackEnd و #FrontEnd به اندازه هم میتونه کاربردی باشه استفاده از static method های Array.from و Array.fromAsync. این نکته هم بگم که Array.fromAsync به تازگی با توجه به آپدیت #V8 در نسخه 22 برای #NodeJS منتشر شده و در نسخه های قبل در دسترس نیست.
حالا کار این متد ها به چه شکل هست با .from شروع میکنیم. شما اگر یک iterable obj داشته باشید شاید بخواید این Object رو تبدیل به Array کنید و معمولا از این تکنیک استفاده میشه.
این استایل از برنامه نویسی بیشتر به نوعی imperative programming محسوب میشه و در زبان های procedural programming خیلی دیده میشه. با این حال که #JavaScript یک زبان Multi-paradigm هست و این استایل کد زدن مجاز هست ولی خیلی در کامینیوتی مرسوم نیست و کلا بیشتر کد های declarative و ترکیب OOP و Functional استفاده میشه. ( هرچند Functional خالص سخت هست در #JavaScript )
حالا اگر بخوایم کد بالا رو یطوری داشته باشیم که مرسوم تر باشه بین برنامه نویس های #JavaScript، در این سناریو متد های Array.from و Array.fromAsync به کمک ما میاد تا کد ما declarative تر بشه.
حالا برای تبدیل کد بالا کافی هست این کار رو کنید و بووم تمام!
اگر بخوام درمورد Array.fromAsync هم بگم این هست که دقیقا به همین شکل کار میکنه و تنها تفاوتش این هست که با async iterable ها و generator ها سازگار هست.
حالا همین رو به این شکل تبدیل میکنیم.
هنوز یک قسمت جالب از داستان مونده بزارید با مثال بهتون نشون بدم.
اگر اینجا دقت کنید میبینید که میتونه سناریو مناسبی برای استفاده از Promise.all باشه ولی استفاده نشده به نظرتون تفاوت چیه؟
با استفاده از Promise.all تمام Promise ها به صورت همزمان تلاش به resolve شدن دارن یعنی داره concurrent انجام میشه اما در این سناریو بدون بلاک شدن event loop به ترتیب Promise ها resolve میشن.
راستی این ویژگی هم از نسخه 1.38 روی #Deno در دسترس بوده و این برای من خیلی جذابه که تیم #Deno اینقدر خوب دارن عمل میکنن. مدتی هست هر حرکتی در اکوسیستم اتفاق میافته #Deno از پرچم داران در سرعت آپدیت و رو به جلو حرکت کردن هست.
#Tip
حالا کار این متد ها به چه شکل هست با .from شروع میکنیم. شما اگر یک iterable obj داشته باشید شاید بخواید این Object رو تبدیل به Array کنید و معمولا از این تکنیک استفاده میشه.
const arr = [];
for (const v of iterableObj) {
arr.push(v);
}
این استایل از برنامه نویسی بیشتر به نوعی imperative programming محسوب میشه و در زبان های procedural programming خیلی دیده میشه. با این حال که #JavaScript یک زبان Multi-paradigm هست و این استایل کد زدن مجاز هست ولی خیلی در کامینیوتی مرسوم نیست و کلا بیشتر کد های declarative و ترکیب OOP و Functional استفاده میشه. ( هرچند Functional خالص سخت هست در #JavaScript )
حالا اگر بخوایم کد بالا رو یطوری داشته باشیم که مرسوم تر باشه بین برنامه نویس های #JavaScript، در این سناریو متد های Array.from و Array.fromAsync به کمک ما میاد تا کد ما declarative تر بشه.
حالا برای تبدیل کد بالا کافی هست این کار رو کنید و بووم تمام!
const arr = Array.from(iterable);
اگر بخوام درمورد Array.fromAsync هم بگم این هست که دقیقا به همین شکل کار میکنه و تنها تفاوتش این هست که با async iterable ها و generator ها سازگار هست.
const arr = [];
for await (const v of asyncIterable) {
arr.push(v);
}
حالا همین رو به این شکل تبدیل میکنیم.
const arr = await Array.fromAsync(asyncIterable);
هنوز یک قسمت جالب از داستان مونده بزارید با مثال بهتون نشون بدم.
Array.fromAsync(
new Set([Promise.resolve(1), Promise.resolve(2), Promise.resolve(3)]),
).then((array) => console.log(array));
// [1, 2, 3]
اگر اینجا دقت کنید میبینید که میتونه سناریو مناسبی برای استفاده از Promise.all باشه ولی استفاده نشده به نظرتون تفاوت چیه؟
با استفاده از Promise.all تمام Promise ها به صورت همزمان تلاش به resolve شدن دارن یعنی داره concurrent انجام میشه اما در این سناریو بدون بلاک شدن event loop به ترتیب Promise ها resolve میشن.
راستی این ویژگی هم از نسخه 1.38 روی #Deno در دسترس بوده و این برای من خیلی جذابه که تیم #Deno اینقدر خوب دارن عمل میکنن. مدتی هست هر حرکتی در اکوسیستم اتفاق میافته #Deno از پرچم داران در سرعت آپدیت و رو به جلو حرکت کردن هست.
#Tip
👍22
سوال مصاحبه درمورد #NestJS
شما وقتی با #NestJS و #TypeScript در حال توسعه #BackEnd هستید خب به صورت روتین از Injectable ها در #NestJS استفاده میکنید.
حالا با فرض این که ما یک EmailService داریم که Injectable هست و میخوایم در سرویس پایین اون رو inject کنیم و استفاده کنیم. به کد پایین دقت کنید.
اینجا همه چی درست و عادی کار میکنه ولی اگر یکم با دقت بیشتری نگاه کنید این کد خیلی غیر عادی هست. باتوجه به این موضوع که در هنگام transpile شدن کد #TypeScript به #JavaScript تایپ ها حذف میشه.
حالا سوال اینجا هست که #NestJS چطور با استفاده از یک type یعنی EmailService متوجه میشه باید چه سرویسی رو inject کنه؟ در حقیقت اینجا از یک type یک logic داره که در برنامه ما استفاده میشه و برسی این black magic میتونه جذاب باشه.
نظراتتون رو کامنت کنید.
#Tip
شما وقتی با #NestJS و #TypeScript در حال توسعه #BackEnd هستید خب به صورت روتین از Injectable ها در #NestJS استفاده میکنید.
حالا با فرض این که ما یک EmailService داریم که Injectable هست و میخوایم در سرویس پایین اون رو inject کنیم و استفاده کنیم. به کد پایین دقت کنید.
@Injectable()
class MyService {
constructor(private readonly emailService : EmailService)
}
اینجا همه چی درست و عادی کار میکنه ولی اگر یکم با دقت بیشتری نگاه کنید این کد خیلی غیر عادی هست. باتوجه به این موضوع که در هنگام transpile شدن کد #TypeScript به #JavaScript تایپ ها حذف میشه.
حالا سوال اینجا هست که #NestJS چطور با استفاده از یک type یعنی EmailService متوجه میشه باید چه سرویسی رو inject کنه؟ در حقیقت اینجا از یک type یک logic داره که در برنامه ما استفاده میشه و برسی این black magic میتونه جذاب باشه.
نظراتتون رو کامنت کنید.
#Tip
👍13
Node Master
یکبار داشتم تست مینوشتم و داشتم type ها رو assert میکردم که به این موضوع خوردم که چند ساعتی داشتم دنبالش میگشتم که داستان چیه و در نهایت متوجه شدم که اگر string رو با String class مستقیم بسازید typeof مربوط بهش میشه object و نه string. const text1 = new S…
چند وقت پیش یک همچین پستی گذاشته بودم که در هنگام تست نوشتن با همچین کدی روبرو شده بودم
جواب این false میشه و یکم برام عجیب بود دوستان هم توضیحات خوبی دادن منطقی و درست بود ولی کامل جوابم رو نگرفتم که چرا اینطوره.
شما اگر قصد دارید با استفاده از function هایی مثل String, Boolean, Number عملیات type conversion انجام بدید اگر از new استفاده کنید در حقیقت typeof برابر با object میشه و کاملا منطقی هست به این دلیل که باهاش مثل constructor function رفتار میشه. حالا object که از این حالت بدست میاد شبیهه به primitive ها رفتار میکنه ولی در همچین سناریویی تفاوت خودش رو نشون میده. دلیل این رفتار هم بخاطر موضوعات تاریخی مربوط به #JavaScript هست و این موضوع هم درنظر داشته باشید که در code base های بروز اصلا منطقی نیست از این موضوع استفاده کنید و کاملا از این موضوع فرار کنید. فقط گاهی ممکن هست بهش بر بخورید پس دونستن این موضوع میتونه بهتون کمک کنه
#Tip
3 === new Number(3)
جواب این false میشه و یکم برام عجیب بود دوستان هم توضیحات خوبی دادن منطقی و درست بود ولی کامل جوابم رو نگرفتم که چرا اینطوره.
شما اگر قصد دارید با استفاده از function هایی مثل String, Boolean, Number عملیات type conversion انجام بدید اگر از new استفاده کنید در حقیقت typeof برابر با object میشه و کاملا منطقی هست به این دلیل که باهاش مثل constructor function رفتار میشه. حالا object که از این حالت بدست میاد شبیهه به primitive ها رفتار میکنه ولی در همچین سناریویی تفاوت خودش رو نشون میده. دلیل این رفتار هم بخاطر موضوعات تاریخی مربوط به #JavaScript هست و این موضوع هم درنظر داشته باشید که در code base های بروز اصلا منطقی نیست از این موضوع استفاده کنید و کاملا از این موضوع فرار کنید. فقط گاهی ممکن هست بهش بر بخورید پس دونستن این موضوع میتونه بهتون کمک کنه
#Tip
👍18
یکی از ویژگی های جدیدی و کاربردی که در #ES2024 اضافه شده و هم برای بچه های #Frontend و هم #Backend میتونه مفید باشه.
یکی از pattern های معروف برای ایجاد یک async function در #JavaScript به این صورت هست.
معمولا از این ویژگی وقتی استفاده میشه که قصد داریم یک wrapper برای یک CPS Style Async Function بنویسیم.
قبلا در مورد این که CPS Style چیست و چرا مفصل صحبت کردیم و میتونید از این لینک مطالعه کنید.
https://t.iss.one/NodeMaster/19
حالا با این API جدید میتونیم کد بالا به این صورت refactor کنیم
با استفاده از static method جدیدی که به Promise اضافه شده یعنی Promise.withResolvers میتونیم از شر constructor خلاص بشیم. ( یجورایی میشه گفت factory pattern حساب میشه )
یک موضوع شاید براتون سوال پیش که چرا گفتم از شر constructor خلاص بشیم. آیا مشکلی داره؟ جواب طبق سایر جواب ها برنامه نویسی میتونیم بگیم بستگی داره. ولی من حس میکنم با توجه به تغییراتی که من میبینیم به مفهوم Aggregation در OOP خیلی احترام بیشتری داره گذاشته میشه.
این آپدیت خیلی جدیده و در حال حاظر در #NodeJS ورژن 22 هستش.
البته دوباره این رو باید بگم که #Deno پرچم داری کرده و از ورژن 1.38 این ویژگی رو زودتر اضافه کرده.
#Tip
یکی از pattern های معروف برای ایجاد یک async function در #JavaScript به این صورت هست.
function job() {
return new Promise((resolve, reject) => resolve(2));
}معمولا از این ویژگی وقتی استفاده میشه که قصد داریم یک wrapper برای یک CPS Style Async Function بنویسیم.
قبلا در مورد این که CPS Style چیست و چرا مفصل صحبت کردیم و میتونید از این لینک مطالعه کنید.
https://t.iss.one/NodeMaster/19
حالا با این API جدید میتونیم کد بالا به این صورت refactor کنیم
function job() {
const { promise, reject, resolve } = Promise.withResolvers();
resolve(2);
return promise;
}با استفاده از static method جدیدی که به Promise اضافه شده یعنی Promise.withResolvers میتونیم از شر constructor خلاص بشیم. ( یجورایی میشه گفت factory pattern حساب میشه )
یک موضوع شاید براتون سوال پیش که چرا گفتم از شر constructor خلاص بشیم. آیا مشکلی داره؟ جواب طبق سایر جواب ها برنامه نویسی میتونیم بگیم بستگی داره. ولی من حس میکنم با توجه به تغییراتی که من میبینیم به مفهوم Aggregation در OOP خیلی احترام بیشتری داره گذاشته میشه.
این آپدیت خیلی جدیده و در حال حاظر در #NodeJS ورژن 22 هستش.
البته دوباره این رو باید بگم که #Deno پرچم داری کرده و از ورژن 1.38 این ویژگی رو زودتر اضافه کرده.
#Tip
Telegram
Node Master
مفهوم CPS Style چیست و در NodeJs به چه صورت هست؟
خب دوستان همین الان بگم که خیلی از افرادی که با Node کار کردن تمام مدت از این استایل استفاده کردن حتی بدون این که اسمش رو بدونن.
بزارید با مثال و کد توضیح بدم خیلی راحت متوجه میشید.
function doSomething() {…
خب دوستان همین الان بگم که خیلی از افرادی که با Node کار کردن تمام مدت از این استایل استفاده کردن حتی بدون این که اسمش رو بدونن.
بزارید با مثال و کد توضیح بدم خیلی راحت متوجه میشید.
function doSomething() {…
👍9
اگر تا حالا فکر کردین که چطور فریمورک ها رو برای ما developer های عادی توسعه میدن جواب شما یک magic هست به اسم #Metaprogramming . این کار مثل برنامه نویسی معمولی که ما انجام میدیم تکنیک های مختلف داره که یکی از اونها رو در این پست باهم برسی کردیم.
https://t.iss.one/NodeMaster/115
البته لازم به ذکر هست یکسری Pattern به صورت کلی وجود داره که بین زبان های مختلف مشترک هست و به نوعی پیاده سازی های مختلف ازش دیده میشه و البته یکسری زبان ها هم یکسری تکنیک های مخصوص به خودشون رو هم دارن که اون ها رو خاص تر میکنه.
حالا یکی از این جادو های کاربردی #Metaprogramming این هست که اگر یک Instance از یک Object داریم که یک Parrent Class داره چطور فقط و فقط متوجه بشیم که چه Attr هایی مخصوص به اون Child Class هست و Attr های Parrent رو نادیده بگیریم. و جواب این سوال خیلی سادس :
در #JavaScript با استفاده از Object.getOwnPropertyNames و Reflect.ownKeys(myObj) میتونیم متوجه بشیم که کدام Atter ها مربوط به Instnace ما یعنی myObj هستند. به این خاطر هست که Atter های Parrent یعنی x و y رو کامل نادیده گرفته میشه و فقط در name رو ما به عنوان Attr میبینم که مستقیما روی Child Instance ما تعریف شده و نه روی Parrent. شاید این مثال یکم پیچیده باشه بخاطر ماهیت Object ها در #JavaScript هست. همین رو اگر بخوایم در #Python برسی کنیم شاید یکم قابل درک تر باشه و البته مثال های دیگ هم در #JavaScript میشه زد ولی خب به نظرم بهتره بزاریم برای کنجکاوی خودتون.
یک نکته خیلی جذاب کلا خارج از بحث که به نظرم ارزش توجه کردن داره استفاده از set برای رسیدن به نتیجه ای شبیه به مثال #JavaScript هست. و اینجا به عنوان مثال مستقیم یکی از کاربرد های Set Object و Set theory رو مستقیم و خیلی کوچیک میبینید.
نکته ای که خیلی مهم باید توجه بشه این هست که بین تکنیک استفاده از ownKeys و getOwnPropertyNames تفاوت هایی وجود داره که اگر استقبال بشه عمیق تر وارد این موضوع میشیم.
#Tip
https://t.iss.one/NodeMaster/115
البته لازم به ذکر هست یکسری Pattern به صورت کلی وجود داره که بین زبان های مختلف مشترک هست و به نوعی پیاده سازی های مختلف ازش دیده میشه و البته یکسری زبان ها هم یکسری تکنیک های مخصوص به خودشون رو هم دارن که اون ها رو خاص تر میکنه.
حالا یکی از این جادو های کاربردی #Metaprogramming این هست که اگر یک Instance از یک Object داریم که یک Parrent Class داره چطور فقط و فقط متوجه بشیم که چه Attr هایی مخصوص به اون Child Class هست و Attr های Parrent رو نادیده بگیریم. و جواب این سوال خیلی سادس :
const myPrototype = { x: 1, y: 2 }; // Parrent
const myObj /* Child */ = Object.create(myPrototype);
myObj.name = "point"; // Instance Prop
console.log(Object.getOwnPropertyNames(myObj)); // [ 'name' ]
console.log(Reflect.ownKeys(myObj)); // [ 'name' ]
console.log("x in myObj :", "x" in myObj);در #JavaScript با استفاده از Object.getOwnPropertyNames و Reflect.ownKeys(myObj) میتونیم متوجه بشیم که کدام Atter ها مربوط به Instnace ما یعنی myObj هستند. به این خاطر هست که Atter های Parrent یعنی x و y رو کامل نادیده گرفته میشه و فقط در name رو ما به عنوان Attr میبینم که مستقیما روی Child Instance ما تعریف شده و نه روی Parrent. شاید این مثال یکم پیچیده باشه بخاطر ماهیت Object ها در #JavaScript هست. همین رو اگر بخوایم در #Python برسی کنیم شاید یکم قابل درک تر باشه و البته مثال های دیگ هم در #JavaScript میشه زد ولی خب به نظرم بهتره بزاریم برای کنجکاوی خودتون.
class Parrent:
def __init__(self) -> None:
self.x = 1
self.y = 2
class Child(Parrent):
def __init__(self) -> None:
super().__init__()
self.name = "point"
myObj = Child()
parrentAttrs = set(dir(Parrent()))
childAtters = set(dir(Child()))
print(childAtters.difference(parrentAttrs))
یک نکته خیلی جذاب کلا خارج از بحث که به نظرم ارزش توجه کردن داره استفاده از set برای رسیدن به نتیجه ای شبیه به مثال #JavaScript هست. و اینجا به عنوان مثال مستقیم یکی از کاربرد های Set Object و Set theory رو مستقیم و خیلی کوچیک میبینید.
نکته ای که خیلی مهم باید توجه بشه این هست که بین تکنیک استفاده از ownKeys و getOwnPropertyNames تفاوت هایی وجود داره که اگر استقبال بشه عمیق تر وارد این موضوع میشیم.
#Tip
Telegram
Node Master
خب first class function یعنی چی؟
به این موضوع هست که شما میتونید با function ها مثل بقیه object ها رفتار کنید. یعنی در متغیر ذخیرشون کنید یک لیستی از function ها داشته باشید و یا حتی در runtime فانکشن جدید بسازید و return کنید.
این موضوع خیلی نکته قوی هست…
به این موضوع هست که شما میتونید با function ها مثل بقیه object ها رفتار کنید. یعنی در متغیر ذخیرشون کنید یک لیستی از function ها داشته باشید و یا حتی در runtime فانکشن جدید بسازید و return کنید.
این موضوع خیلی نکته قوی هست…
👍8
Node Master
اگر درحال یادگیری #NestJS هستید و یا مدت زیادی هست با این framework محبوب کار میکنید به این نکته حتما توجه کنید. 1. به هیچ عنوان از Nest CLI برای ایجاد یک پروژه جدید استفاده نکنید. 2. حداقل اگر استفاده میکنید سعی کنید dep های اضافه رو پاک کنید. درمورد نکته…
ترسناک تر از Dynamic Type بودن #JavaScript در حقیقت پروژه #TypeScript هست که به تو توهم Type safe بودن بده.
هروقت پروژه #TypeScript دیدین اول بیاین این قسمت رو چک کنید که مثل عکس بالا strict باشه و هیچ کدوم از flag های زیرش false نباشه.
اگر در موقع کار با #TypeScript مجبور شدین اینجا فلگی رو false کنید این برداشت رو میتونید کنید که #TypeScript بلد نیستید!
هروقت پروژه #TypeScript دیدین اول بیاین این قسمت رو چک کنید که مثل عکس بالا strict باشه و هیچ کدوم از flag های زیرش false نباشه.
اگر در موقع کار با #TypeScript مجبور شدین اینجا فلگی رو false کنید این برداشت رو میتونید کنید که #TypeScript بلد نیستید!
👍19
به این خط ساده و کوچک دقت کنید، توانایی این رو داره هرپروژه #FrontEnd و #BackEnd که با #NodeJS توسعه داده شده رو تبدیل به جهنم کنه.
اگر در #TypeScript براتون سوال پیش اومده که چرا در try catch statement تایپ err نامشخص هست، دقیقا بخاطر این موضوع هست. به این دلیل که هر نوع Object رو میشه throw کرد (این خیلی ترسناکه) و چون #JavaScript مفهومی به اسم Compile Time Error نداره و با توجه به طبیعت Dynamic و البته مفسری که #JavaScript داره منطقی هست که شما وقتی try catch استفاده میکنی type برای error تا زمان runtime مشخص نباشه. با مثال پایین بیشتر به عمق مسئله پی میبرید.
معمولا بعضیا با استفاده از type cast تایپ error رو تبدیل به Error میکنن مثل کد زیر که این به نوع خودش میتونه یک فاجعه دیگه باشه ( آخه نابغه اگر تایپ مشخص بود که Error هست #TypeScript همون اول خودش Error میزاشت و نیاز به Type Cast نبود دیگه)
خب حالا سناریو های بد رو دیدم چطور جلوگیری کنیم؟ در پروژه های #FontEnd تنها روش خیلی خوبی که وجود داره استفاده از instanceof هست در #NodeJS برای #BackEnd هم میشه از این روش استفاده کرد ولی یک تکنیک دیگه وجود داره که اون بیشتر برای سناریوهای خیلی خاص #NodeJS هم کاربردی هست.
برای پروژه های #NodeJS در std مربوط به Node یک فانکشن کمکی هست به اسم isNativeError که همین کار instanceof رو میکنه. حالا سوال پیش میاد که چرا باید از این استفاده کنیم؟ در حالت هایی به عنوان مثال استفاده از "node:vm" و ایجاد یک context جدید میتونه دردسر ساز بشه و instanceof نتونه تشخیص بده Error رو که نتایجش هم مشخصه. نکات دیگه ای هم وجود داره که پیشنهاد میکنم داکیومنت مربوط به این بخش رو بخونید کامل با مثال ساده توضیح داده.
حالا یک سوال دیگ شاید براتون پیش بیاد که چرا اینقدر بدبینانه به مسئله نگاه میکنیم؟
تو دنیایی که #NPM وجود داره اعتماد به پکیج های 3RD Party گاهی اوقات میتونه گرون تموم بشه. شاید اون پکیج که استفاده میکنید این داستان رو رعایت نکرده باشه. پس بهتره ما دقت کنیم تا از runtime ارور های نصف شب جلوگیری کنیم و با آسوده بخوابیم.
throw 1;
اگر در #TypeScript براتون سوال پیش اومده که چرا در try catch statement تایپ err نامشخص هست، دقیقا بخاطر این موضوع هست. به این دلیل که هر نوع Object رو میشه throw کرد (این خیلی ترسناکه) و چون #JavaScript مفهومی به اسم Compile Time Error نداره و با توجه به طبیعت Dynamic و البته مفسری که #JavaScript داره منطقی هست که شما وقتی try catch استفاده میکنی type برای error تا زمان runtime مشخص نباشه. با مثال پایین بیشتر به عمق مسئله پی میبرید.
try {
throw { hoo: "Pop up from stack , NodeMaster" };
} catch (err /* type => unknown */) {
console.log(err);
}معمولا بعضیا با استفاده از type cast تایپ error رو تبدیل به Error میکنن مثل کد زیر که این به نوع خودش میتونه یک فاجعه دیگه باشه ( آخه نابغه اگر تایپ مشخص بود که Error هست #TypeScript همون اول خودش Error میزاشت و نیاز به Type Cast نبود دیگه)
try {
throw { hoo: "Pop up from stack , NodeMaster" };
} catch (err) {
console.log((err as Error).message); // WTFFFFFFFFF !!!!
}خب حالا سناریو های بد رو دیدم چطور جلوگیری کنیم؟ در پروژه های #FontEnd تنها روش خیلی خوبی که وجود داره استفاده از instanceof هست در #NodeJS برای #BackEnd هم میشه از این روش استفاده کرد ولی یک تکنیک دیگه وجود داره که اون بیشتر برای سناریوهای خیلی خاص #NodeJS هم کاربردی هست.
try {
throw { hoo: "Pop up from stack , NodeMaster" };
} catch (err) {
if (err instanceof Error) {
console.error("it's valid error object", err);
} else {
console.error("WHAT THE F IS THIS ???", err);
}
}برای پروژه های #NodeJS در std مربوط به Node یک فانکشن کمکی هست به اسم isNativeError که همین کار instanceof رو میکنه. حالا سوال پیش میاد که چرا باید از این استفاده کنیم؟ در حالت هایی به عنوان مثال استفاده از "node:vm" و ایجاد یک context جدید میتونه دردسر ساز بشه و instanceof نتونه تشخیص بده Error رو که نتایجش هم مشخصه. نکات دیگه ای هم وجود داره که پیشنهاد میکنم داکیومنت مربوط به این بخش رو بخونید کامل با مثال ساده توضیح داده.
import { types } from "node:util";
try {
throw { hoo: "Pop up from stack , NodeMaster" };
} catch (err) {
if (types.isNativeError(err)) {
console.error("it's valid error object", err);
} else {
console.error("WHAT THE F IS THIS ???", err);
}
}حالا یک سوال دیگ شاید براتون پیش بیاد که چرا اینقدر بدبینانه به مسئله نگاه میکنیم؟
تو دنیایی که #NPM وجود داره اعتماد به پکیج های 3RD Party گاهی اوقات میتونه گرون تموم بشه. شاید اون پکیج که استفاده میکنید این داستان رو رعایت نکرده باشه. پس بهتره ما دقت کنیم تا از runtime ارور های نصف شب جلوگیری کنیم و با آسوده بخوابیم.
👍16
یک Pattern وجود داره که خیلی درموردش صحبت نمیشه در اکوسیستم #JavaScript چه پروژه های #FrontEnd و چه #Backend که با #NodeJS و بقیه runtime ها توسعه داده شده باشن. این پترن خیلی ساده هست. استفاده نکردن ( یا حداقل استفاده ) از Anonymous function ها میباشد.
حالا سوال پیش میاد چرا از این پترن باید استفاده کنیم؟
وقتی دارید برنامه توسعه میدین و به نوعی چه توسط خودتون یا Framework که استفاده میکنید با فرایند IOC درگیر هستید مثل #React یا حتی #Express و ... اگر سایز پروژه بزرگ باشه برای پیدا کردن Bug ها به هیچ عنوان تکنیک console.log راه بهینه ای نیست. و معمولا از ابزار ها و تکنیک های مختلف در کنار هم استفاده میشن تا این فرایند راحت تر باشه. در کنار این مفاهیم لاگ کردن Error ها و stack trace مربوط بهشون خیلی مهم هست و خیلی کمک میکنه تا scope مربوط به به باگ رو کوچک تر کنیم و سریعتر بتونیم باگ رو پیدا کنیم.
با استفاده زیاد از Anonymous function ها که معمولا بیشتر در هنگام arg برای پاس دادن به عنوان callback استفاده میشن، stack trace شکل خوبی نخواهد داشت و اگر زیاد استفاده بشه حتی stack trace میتونه کاملا بی مصرف بشه و با این کار یکی از عناصر خیلی مهم برای debug کردن رو از دست میدیم. به مثال زیر توجه کنید.
اینجا سایز پروژه کوچک هست و راحت میشه Error رو پیدا کرد چون جزیات زیادی در stack وجود نداره و کد framework هم در نظر گرفته نشده. اما توجه داشته باشید که اون خط آخر یعنی Object.anonymous در شرایط فشار باگ روی production خیلی میتونه ترسناک باشه.یک نکته که حتی میتونه وحشتناک تر کنه داستان رو پروژه #TypeScript بدون source map و اگر به این ترکیب esbuild هم اضافه بشه جای صحبتی اصلا باقی نمیمونه.
حالا با یک مثال واقعی تر و خیلی ساده این موضوع رو برسی میکنیم
این مثال کیلومتر ها با پیچدگی پروژه های production فاصله داره اما همین کد ساده نشون میده چقدر توجه به این نکته میتونه ساعت ها از وقت شما نجات بده و کار کم استرس
تری هم تجربه کنید. مشکل دقیقا خط اول stack trace هست که هیچی ازش وجود نداره ( در این مثال خوش شانسیم که خطی که این اتفاق افتاده دقیقا اشاره داره به همون callback ما ولی همیشه اینطور نیست )
برای داشتن زندگی شیرین تر کافیه کمتر از Anonymous function ها چه به شکل arrow و چه با function keyword استفاده کنید. و برای function ها نام مناسب انتخاب کنید. مثل سناریو پایین که rootHandler رو داریم.
حالا چند نکته باید در نظر بگیرید.
- تفاوت arrow function و function keyword رو بدونید گاهی ممکنه دردسر ساز بشه.
- اگر از #TypeScript استفاده میکنید از اهمیت source map هرگز غافل نشید.
#Tip
حالا سوال پیش میاد چرا از این پترن باید استفاده کنیم؟
وقتی دارید برنامه توسعه میدین و به نوعی چه توسط خودتون یا Framework که استفاده میکنید با فرایند IOC درگیر هستید مثل #React یا حتی #Express و ... اگر سایز پروژه بزرگ باشه برای پیدا کردن Bug ها به هیچ عنوان تکنیک console.log راه بهینه ای نیست. و معمولا از ابزار ها و تکنیک های مختلف در کنار هم استفاده میشن تا این فرایند راحت تر باشه. در کنار این مفاهیم لاگ کردن Error ها و stack trace مربوط بهشون خیلی مهم هست و خیلی کمک میکنه تا scope مربوط به به باگ رو کوچک تر کنیم و سریعتر بتونیم باگ رو پیدا کنیم.
با استفاده زیاد از Anonymous function ها که معمولا بیشتر در هنگام arg برای پاس دادن به عنوان callback استفاده میشن، stack trace شکل خوبی نخواهد داشت و اگر زیاد استفاده بشه حتی stack trace میتونه کاملا بی مصرف بشه و با این کار یکی از عناصر خیلی مهم برای debug کردن رو از دست میدیم. به مثال زیر توجه کنید.
function iocContainer(cb) {
cb()
}
iocContainer(() => { throw new Error("ugly stack trace") })at /home/imanhpr/codes/main.js:6:28
at iocContainer (/home/imanhpr/codes/main.js:2:5)
at Object.<anonymous> (/home/imanhpr/codes/main.js:6:1)
اینجا سایز پروژه کوچک هست و راحت میشه Error رو پیدا کرد چون جزیات زیادی در stack وجود نداره و کد framework هم در نظر گرفته نشده. اما توجه داشته باشید که اون خط آخر یعنی Object.anonymous در شرایط فشار باگ روی production خیلی میتونه ترسناک باشه.یک نکته که حتی میتونه وحشتناک تر کنه داستان رو پروژه #TypeScript بدون source map و اگر به این ترکیب esbuild هم اضافه بشه جای صحبتی اصلا باقی نمیمونه.
حالا با یک مثال واقعی تر و خیلی ساده این موضوع رو برسی میکنیم
const express = require("express")
const app = express()
app.get("/", (req, res) => {
throw new Error("ugly error")
})
app.listen(3000)Error: ugly error
at /home/imanhpr/codes/main.js:6:11
at Layer.handle [as handle_request] (/home/imanhpr/codes/node_modules/express/lib/router/layer.js:95:5)
at next (/home/imanhpr/codes/node_modules/express/lib/router/route.js:149:13)
at Route.dispatch (/home/imanhpr/codes/node_modules/express/lib/router/route.js:119:3)
at Layer.handle [as handle_request] (/home/imanhpr/codes/node_modules/express/lib/router/layer.js:95:5)
at /home/imanhpr/codes/node_modules/express/lib/router/index.js:284:15
at Function.process_params (/home/imanhpr/codes/node_modules/express/lib/router/index.js:346:12)
at next (/home/imanhpr/codes/node_modules/express/lib/router/index.js:280:10)
at expressInit (/home/imanhpr/codes/node_modules/express/lib/middleware/init.js:40:5)
at Layer.handle [as handle_request] (/home/imanhpr/codes/node_modules/express/lib/router/layer.js:95:5)
این مثال کیلومتر ها با پیچدگی پروژه های production فاصله داره اما همین کد ساده نشون میده چقدر توجه به این نکته میتونه ساعت ها از وقت شما نجات بده و کار کم استرس
تری هم تجربه کنید. مشکل دقیقا خط اول stack trace هست که هیچی ازش وجود نداره ( در این مثال خوش شانسیم که خطی که این اتفاق افتاده دقیقا اشاره داره به همون callback ما ولی همیشه اینطور نیست )
برای داشتن زندگی شیرین تر کافیه کمتر از Anonymous function ها چه به شکل arrow و چه با function keyword استفاده کنید. و برای function ها نام مناسب انتخاب کنید. مثل سناریو پایین که rootHandler رو داریم.
app.get("/", function rootHandler(req, res) {
throw new Error("ugly error")
})
// OR
const rootHandler = (req, res) => {
throw new Error("ugly error")
}
app.get("/", rootHandler)
Error: ugly error
at rootHandler (/home/imanhpr/codes/main.js:6:11)
at Layer.handle [as handle_request] (/home/imanhpr/codes/node_modules/express/lib/router/layer.js:95:5)
حالا چند نکته باید در نظر بگیرید.
- تفاوت arrow function و function keyword رو بدونید گاهی ممکنه دردسر ساز بشه.
- اگر از #TypeScript استفاده میکنید از اهمیت source map هرگز غافل نشید.
#Tip
👍15
یک خورده دارم #React مرور میکنم برای پروژه شخصی. یک موضوعی که به ذهنم اومد این هست که چطور موقع هندل کردن event ها با handler function ها چطور stack trace تمیزی داشته باشیم.
در این پست درمورد این موضوع و این که چطور stack trace تمیزی داشته باشیم با مثال #Express روی #NodeJS صحبت کردیم.
https://t.iss.one/NodeMaster/228
در این پست هم راجع به Reflection اشاره ای کردیم.
https://t.iss.one/NodeMaster/121
حالا شما component زیر که خیلی ساده هست رو در نظر بگیرید
بزارید همین اول بگم این نکته شاید خیلی زیاده روی باشه و نیاز نباشه ولی خب میتونه برای درک بهتر Reflection درنظر گرفتش. تا اینجا باتوجه به چیزایی که میدونم stack trace خوبی خواهیم داشت به دلیل این که clickHandler اسم داره.
سناریویی رو در نظر بگیرید که دارید روی یک سری دیتا loop میزنید و برای هر Entity که دارید یک clickHandler ایجاد میکنید. سوال پیش میاد وقتی روی یکی از این function ها کلیک و call میشه چطور بدونیم کدوم call شده دقیق؟
۱. راه حل ساده تر و همیشه جواب log کردن هست.
۲. راه حل پیچیده تر کمک از Reflection و تغییر اسم function در runtime.
دوستان لزوما نیازی نیست از Reflection استفاده کنید. با log کردن صحیح نیازی اصلا ندارید و فقط این روش پیچدگی بیهوده اضاف میکنه و صرفا برا عمیق شدن داریم میریم جلو.
در اینجا من اومدم به اسم فانکشن Id که به عنوان prop اومده رو در runtime اضافه میکنم و خب این دقیقا معادل همچین چیزی میشه.
اسم فانکشن به صورت عادی یکی از چیزایی هست که زمان compile time ( یا اینجا dev time میشه بهش گفت هرچند خیلی مرسوم نیست) مشخص میشه و خب وقتی چیزی رو در این زمان داشته باشیم dynamic کردنش نزدیک به غیرممکن هست.
حالا اینجا Reflection بهمون کمک میکنه که در runtime یک چیزی که به صورت عادی دردسترس نیست رو تغییر بدیم مثل name atter برای function ها که در این مثال دارید میبینید و دقیقا این موضوع معادل کد clickHandler_2 هست با این تفاوت که در runtime ایجاد میشه و نه compile time.
#Tip
در این پست درمورد این موضوع و این که چطور stack trace تمیزی داشته باشیم با مثال #Express روی #NodeJS صحبت کردیم.
https://t.iss.one/NodeMaster/228
در این پست هم راجع به Reflection اشاره ای کردیم.
https://t.iss.one/NodeMaster/121
حالا شما component زیر که خیلی ساده هست رو در نظر بگیرید
function SimpleComp() {
function clickHandler() {
console.log("handler fn :", clickHandler.name);
}
return <button onClick={clickHandler}>click here!</button>;
}بزارید همین اول بگم این نکته شاید خیلی زیاده روی باشه و نیاز نباشه ولی خب میتونه برای درک بهتر Reflection درنظر گرفتش. تا اینجا باتوجه به چیزایی که میدونم stack trace خوبی خواهیم داشت به دلیل این که clickHandler اسم داره.
سناریویی رو در نظر بگیرید که دارید روی یک سری دیتا loop میزنید و برای هر Entity که دارید یک clickHandler ایجاد میکنید. سوال پیش میاد وقتی روی یکی از این function ها کلیک و call میشه چطور بدونیم کدوم call شده دقیق؟
۱. راه حل ساده تر و همیشه جواب log کردن هست.
۲. راه حل پیچیده تر کمک از Reflection و تغییر اسم function در runtime.
دوستان لزوما نیازی نیست از Reflection استفاده کنید. با log کردن صحیح نیازی اصلا ندارید و فقط این روش پیچدگی بیهوده اضاف میکنه و صرفا برا عمیق شدن داریم میریم جلو.
function SimpleComp({ id }) {
function clickHandler() {
console.log("handler fn :", clickHandler.name);
}
Reflect.defineProperty(clickHandler, "name", {
value: clickHandler.name + "_" + id,
});
return <button onClick={clickHandler}>click here!</button>;
}در اینجا من اومدم به اسم فانکشن Id که به عنوان prop اومده رو در runtime اضافه میکنم و خب این دقیقا معادل همچین چیزی میشه.
function clickHandler_2 (){}اسم فانکشن به صورت عادی یکی از چیزایی هست که زمان compile time ( یا اینجا dev time میشه بهش گفت هرچند خیلی مرسوم نیست) مشخص میشه و خب وقتی چیزی رو در این زمان داشته باشیم dynamic کردنش نزدیک به غیرممکن هست.
حالا اینجا Reflection بهمون کمک میکنه که در runtime یک چیزی که به صورت عادی دردسترس نیست رو تغییر بدیم مثل name atter برای function ها که در این مثال دارید میبینید و دقیقا این موضوع معادل کد clickHandler_2 هست با این تفاوت که در runtime ایجاد میشه و نه compile time.
#Tip
Telegram
Node Master
یک Pattern وجود داره که خیلی درموردش صحبت نمیشه در اکوسیستم #JavaScript چه پروژه های #FrontEnd و چه #Backend که با #NodeJS و بقیه runtime ها توسعه داده شده باشن. این پترن خیلی ساده هست. استفاده نکردن ( یا حداقل استفاده ) از Anonymous function ها میباشد.
…
…
👍11