راهنمای جامع تایپ اسکریپت (Typescript) — از صفر تا صد
Typescript یک ابرمجموعه نوعبندی شده از جاوا اسکریپت و هدف آن تسهیل توسعه اپلیکیشنهای بزرگ جاوا اسکریپت است. تایپ اسکریپت مفاهیم رایجی مانند کلاسها، ژنریکها، اینترفیسها و انواع استاتیک را به جاوا اسکریپت میافزاید و به توسعهدهندگان امکان میدهد که از ابزارهایی همچون بررسی استاتیک و «بازسازی» (Refactoring) کد استفاده کنند.
Typescript چه اهمیتی دارد؟
در واقع سؤال فوق را میتوان این گونه نیز بیان کرد که چرا باید از تایپ اسکریپت استفاده کرد؟ در ادامه برخی از دلایلی که توسعهدهندگان جاوا اسکریپت باید یادگیری Typescript را در نظر داشته باشند توضیح میدهیم.
نوعبندی استاتیک: جاوا اسکریپت یک زبان برنامهنویسی با نوعبندی دینامیک است یعنی تا زمانی که وهلهای از یک متغیر را در زمان اجرا ایجاد نکنید در مورد نوع متغیر اطلاعی ندارد و همین مسئله موجب بروز مشکلات و خطاهایی در پروژه میشود. Typescript پشتیبانی از نوعبندی استاتیک را به جاوا اسکریپت اضافه کرده است که موجب میشود از بروز باگهایی که ناشی از تصور نادرست در مورد نوع متغیر هستند جلوگیری شود. ما همچنان در صورتی که از نوع متغیر استفاده کنیم، کنترل کاملی روی میزان صراحت نوع متغیر در کد خود داریم.
پشتیبانی بهتر از IDE: یکی از بزرگترین مزیتهای Typescript نسبت به جاوا اسکریپت، پشتیبانی عالی از IDE است که شامل Intellisense، اطلاعات آنی از کامپایلر Typescript، دیباگ کردن و مواردی از این دست میشود. همچنین برخی اکستنشنهای عالی برای ارتقای بیشتر تجربه توسعه Typescript وجود دارند.
دسترسی به قابلیتهای جدید ECMAScript: تایپاسکریپت امکان دسترسی به جدیدترین قابلیتهای ECMAScript را میدهد و آنها را به اهداف ECMAScript مورد نظر شما تبدیل میکند. این بدان معنی است که میتوانید اپلیکیشنها را با استفاده از جدیدترین ابزارها بدون نیاز به نگرانی در مورد پشتیبانی از مرورگر توسعه دهید.
چه هنگام باید از Typescript استفاده کنیم؟
تا به اینجا متوجه شدم که چرا تایپاسکریپت مفید است و چگونه میتواند تجربه توسعه ما را ارتقا ببخشد. اما تایپاسکریپت راهحلی برای همه چیز محسوب نمیشود و قطعاً به خودی خود نمیتواند از کدنویسی بد جلوگیری کند. بنابراین در ادامه نگاهی به جاهایی میاندازیم که قطعاً بهتر است از تایپاسکریپت استفاده کنیم.
زمانی که کدبیس بزرگی وجود دارد: تایپاسکریپت یک ارتقای مهم برای کدبیس های بزرگ محسوب میشود، چون کمک میکند از بروز بسیاری از خطاهای رایج پیشگیری کنیم. این واقعیت به طور خاص در مواردی که توسعهدهندگان زیادی روی پروژه منفرد کار کنند صدق میکند.
زمانی که شما و تیمتان از قبل با زبانهای دارای نوعبندی استاتیک آشنا باشید: موقعیت بدیهی دیگری که استفاده از تایپاسکریپت در آن توصیه میشود هنگامی است که شما و تیمتان با زبانهای دارای نوعبندی استاتیک مانند جاوا و C# آشنا باشید و نخواهید از روش نگارش کدهای جاوا اسکریپت استفاده کنید.
راهاندازی Typescript
برای راهاندازی تایپاسکریپت، کافی است آن را با ابزار مدیریت بسته npm نصب کرده و یک فایل تایپاسکریپت جدید بسازیم:
npm install -g typescript
پس از نصب کردن تایپاسکریپت میتوانیم نگاهی به ساختار و قابلیتهایی که در اختیار ما قرار میدهد داشته باشیم.
نوعها
اینک نوبت آن رسیده است که ببینیم تایپاسکریپت چه نوعهایی را در اختیار ما قرار میدهد.
نوع عددی
همه اعداد در تایپاسکریپت مقادیر اعشاری هستند. همه این مقادیر نوع عددی میگیرند و این وضعیت شامل مقادیر باینری و هگزادسیمال نیز میشود.
1let num: number = 0.222;
2let hex: number = 0xbeef;
3let bin: number = 0b0010;
نوع رشته
تایپاسکریپت مانند زبانهای دیگر از نوع داده String برای ذخیره دادههای متنی استفاده میکند.
1let str: string = 'Hello World!';
شما در تایپاسکریپت میتوانید با قرار دادن رشته درون بکتیک (``) از رشتههای چندخطی و همچنین عبارتهای جاسازیشده (embed) استفاده کنید.
1let multiStr: string = `A simple
2multiline string!`
3let expression = 'A new expression'
4let expressionStr: string = `Expression str: ${ expression }`
نوع بولی
تایپاسکریپت از اغلب انواع داده ابتدایی پشتیانی میکند که شامل مقادیر بولی نیز میشوند. این مقادیر تنها میتوانند شامل دو مقدار درست و نادرست باشند.
1let boolFalse: boolean = false;
2let boolTrue: boolean = true;
انتساب نوع
اینک که با انواع داده ابتدایی آشنا شدیم، میتوانیم به بررسی روش انتساب نوعها در تایپاسکریپت بپردازیم. بدین منظور اساساً کافی است که نوع متغیر را پس از نام آن و یک کاراکتر دونقطه (:) بنویسید.
نوع منفرد
در ادامه مثالی را مشاهده میکنید که نوع داده رشتهای را به یک متغیر انتساب میدهد:
1let str: string = 'Hello World'
این قالب در مورد همه انواع متغیر صدق میکند.
انواع چندگانه
با استفاده از عملگر (|) امکان انتساب چند نوع داده مختلف به متغیرها نیز وجود دارد:
1let multitypeVar: string | number = 'String'
2multitypeVar = 20
در این روش دو نوع را با استفاده از عملگر | به متغیر خود انتساب میدهیم. بدین ترتیب میتوانیم در آن رشته و همچنین عدد ذخیره کنیم.
بررسی نوعها
اکنون نوبت آن رسیده است که بررسی کنیم آیا متغیرهای ما نوع صحیحی دارند یا نه. ما چندین گزینه به این منظور داریم، اما تنها دو مورد از انواع پراستفاده یعنی Typeof و Instanceof را بررسی میکنیم.
Typeof
دستور Typeof تنها با انواع داده ابتدایی آشنایی دارد. این بدان معنی است که این دستور تنها میتواند متغیری را از یکی از انواع داده که در بخش قبل اشاره کردیم بررسی کند:
1let str: string = 'Hello World!'
2if(typeof str === number){
3 console.log('Str is a number')
4} else {
5 console.log('Str is not a number')
6}
در این مثال یک متغیر رشتهای ایجاد میکنیم و از دستور typeof استفاده میکنیم تا بررسی کنیم که آیا str از نوع عددی است یا نه (که همواره نادرست است). سپس عدد بودن یا نبودن آن را نمایش میدهیم.
Instanceof
عملگر Instanceof تقریباً همانند Typeof است و تنها تفاوت این است که میتواند انواع سفارشی را که از قبل از سوی جاوا اسکریپت تعریف نشدهاند را نیز بررسی کند.
1class Human{
2 name: string;
3 constructor(data: string) {
4 this.name = data;
5 }
6}
7let human = new Human('Gabriel')
8if(human instanceof Human){
9 console.log(`${human.name} is a human`)
10}
در کد فوق یک نوع سفارشی داریم که در ادامه این مقاله آن را بیشتر بررسی خواهیم کرد. فعلاً یک وهله از آن میسازیم و سپس بررسی میکنیم که آیا واقعاً متغیری از نوع Human است یا نه و نتیجه را در کنسول نمایش میدهیم.
تأکید بر نوع
برخی اوقات لازم میشود که متغیرهای خود را به نوعهای خاصی تبدیل کنیم. این موارد غالباً زمانی رخ میدهند که یک نوع عمومی مانند any انتساب داده باشیم و بخواهیم تابعهایی از نوع خاص استفاده کنیم. چندین گزینه برای حل این مشکل وجود دارد، اما در ادامه تنها دو مورد را بررسی میکنیم.
کلیدواژه as
با استفاده از کلیدواژه as پس از نام متغیر و سپس اشاره به نوع داده جدید میتوان به سادگی، نوع یک متغیر را تغییر داد.
1let str: any = 'I am a String'
2let strLength = (str as string).length
عملگر <>
همچنین میتوانیم از عملگر <> استفاده کنیم که دقیقاً همان تأثیر کلیدواژه as را با ساختاری متفاوت به دست میدهد.
1let str: any = 'I am a String'
2let strLength = (<string>str).length
این قطعه کد دقیقاً همان کارکرد قطعه کد قبلی را دارد. تنها ساختار آن متفاوت است.
آرایهها
آرایهها در تایپاسکریپت مجموعهای از اشیای یکسان هستند و میتوانند به دو روش متفاوت ایجاد شوند.
ایجاد آرایهها
روشهای مختلف ایجاد آرایه را در ادامه مشاهده میکنید.
با استفاده از []
میتوان یک آرایه را با نوشتن نوع و سپس [] برای نمایش این که یک آرایه است ایجاد کرد.
1let strings: string[] = ['Hello'، 'World'، '!']
در این مثال، یک آرایه رشتهای میسازیم که سه مقدار رشتهای متفاوت را در خود نگهداری میکند.
با استفاده از نوع آرایه ژنریک
امکان تعریف یک آرایه با استفاده از نوع ژنریک به صورت نوشتن Array<Type> نیز وجود دارد:
1let numbers: Array<number> = [1، 2، 3، 4، 5]
در این روش یک آرایه عددی میسازیم که 5 مقدار عددی متفاوت را نگهداری میکند.
آرایههای چندگانه
به علاوه میتوانیم انواع چندگانهای را با استفاده از یک عملگر | به یک آرایه انتساب دهیم.
1let stringsAndNumbers: (string | number)[] = ['Age'، 20]
در این مثال، یک آرایه ایجاد کردهایم که میتواند مقادیر رشتهای و عددی را نگهداری کنید.
آرایههای چندبعدی
تایپاسکریپت امکان تعریف آرایه چندبعدی را نیز میدهد و معنی آن این است که میتوانیم یک آرایه را درون آرایه دیگر ذخیره کنیم. بدین ترتیب میتوانیم آرایه چندبعدی را با استفاده از عملگرهای چندگانه [] پس از همدیگر تعریف کنیم.
1let numbersArray: number[][] = [[1،2،3،4،5]، [6،7،8،9،10]]
در مثال فوق یک آرایه تعریف کردهایم که آرایه عددی دیگری را نگهداری میکند.
چندتایی
چندتاییها اساساً شبیه به آرایه هستند و تنها یک تفاوت کلیدی با آن دارند. تفاوت این است که میتوان نوع دادهای که در هر موقعیت ذخیره خواهد شد را تعیین کرد و این بدان معنی است که با شمارش انواع مختلف درون براکتهای مربعی، میتوانیم انواعی برای اندیسها تعیین کنیم.
1let exampleTuple: [number، string] = [20، 'https://google.com'];
در مثال فوق یک چندتایی ساده ساختهایم که در اندیس 0 عدد و در اندیس 1 رشته دارد. این بدان معنی است که اگر تلاش کنیم نوع داده متفاوتی در این اندیس قرار دهیم با خطایی مواجه خواهیم شد.
در ادامه مثالی از یک چندتایی نامعتبر را میبینید:
1const exampleTuple: [string، number] = [20، 'https://google.com'];
Enum-ها
Enum-ها در تایپاسکریپت شبیه به دیگر زبانهای برنامهنویسی شیءگرا هستند و امکان تعریف کردن مجموعهای از ثابتهای دارای نام را به ما میدهند. تایپاسکریپت هم Enum-های مبتنی بر عدد و هم مبتنی بر رشته دارد. Enum-ها در تایپاسکریپت با استفاده از کلیدواژه enum تعریف میشوند.
عددی
ابتدا نگاهی به enum-های عددی خواهیم داشت که در آن مقدار یک کلید با یک اندیس تطبیق مییابد.
1enum State{
2 Playing = 0,
3 Paused = 1,
4 Stopped = 2
5}
در کد فوق اقدام به تعریف یک enum عددی میکنیم که Playing با 0 مقداردهی میشود، مقدار Paused برابر با 1 و همین طور تا آخر است.
1enum State{
2 Playing,
3 Paused,
4 Stopped
5}
همچنین میتوانیم مقداردهی را خالی بگذاریم تا تایپاسکریپت به صورت خودکار شروع به اندیسگذاری از صفر بکند.
رشته
تعریف کردن یک enum رشتهای در تایپاسکریپت کار آسانی است و کافی است مقادیر را با رشتهها مقداردهی کنیم.
1enum State{
2 Playing = 'PLAYING',
3 Paused = 'PAUSED',
4 Stopped = 'STOPPED'
5}
در کد فوق یک enum رشتهای را با مقداردهی States به وسیله رشتهها تعریف کردهایم.
شییءها
منظور از شیء در جاوا اسکریپت وهلهای است که شامل مجموعهای از جفتهای کلید-مقدار است. این مقادیر میتوانند متغیر، آرایه یا حتی تابع باشند. همچنین آن را میتوان به صورت نوع دادهای تصور کرد که انواع غیر مقدماتی را نمایش میدهد.
با استفاده از آکولاد میتوان شیء ایجاد کرد:
1const human = {
2 firstName: 'Frank',
3 age: 32,
4 height: 185
5};
در کد فوق یک شیء human ساختهایم که سه جفت مختلف کلید-مقدار دارد. همچنین میتوانیم تابعهایی را به شیء خود اضافه کنیم:
1const human = {
2 firstName: 'Frank',
3 age: 32,
4 height: 185,
5 greet: function(){
6 console.log("Greetings stranger!")
7 }
8};
انواع سفارشی
تایپاسکریپت امکان تعریف انواع سفارشی را نیز فراهم ساخته است که «اسم مستعار» (alias) نام دارد و میتوان در ادامه به سهولت از آنها استفاده مجدد کرد. برای ایجاد نوع سفارشی کافی است از کلیدواژه type استفاده کرده و نوع مورد نظر خود را تعریف کنیم.
1type Human = {firstName: string، age: number، height: number}
در این مثال، به تعریف یک نوع سفارشی با نام Human و مشخصات مورد نظر میپردازیم. اینک نگاهی به روشی ایجاد یک شیء با این نوع خواهیم داشت:
1firstName const human: Human = {firstName: ‘Franz’، age: 32، height: 185}
در کد فوق یک وهله از نوع سفارشی ایجاد کرده و مشخصههای مورد نیاز را تعیین میکنیم.
پارامترهای تابع و نوعهای بازگشتی
تایپاسکریپت به ما امکان میدهد که انواعی برای پارامترهای تابع خود تعیین کرده و نوع بازگشتی را تعیین کنیم. اینک نگاهی به ساختار مورد نیاز برای تعریف کردن یک تابع با استفاده از تایپاسکریپت خواهیم داشت.
1function printState(state: State): void {
2 console.log(`The song state is ${state}`)
3}
4function add(num1: number, num2: number): number {
5 return num1 + num2
6}
در کد فوق دو تابع نمونه داریم که هر دو پارامترهایی با انواع تعریف شده دارند. همچنین میبینیم که نوع بازگشتی پس از بستن پرانتزها تعریف شده است.
اکنون میتوانیم تابع خود را مانند یک تابع معمولی جاوا اسکریپت فراخوانی کنیم، اما کامپایلر بررسی خواهد کرد که آیا تابع با پارامترهای صحیحی ارائه شده است یا نه.
1add(2, 5)
2add(1) // Error to few parameters
3add(5, '2') // Error the second argument must be type number
مشخصههای اختیاری
تایپاسکریپت امکان تعریف کردن مشخصههای اختیاری را نیز برای تابع میدهد. این کار با استفاده از عملگر ? صورت میگیرد نمونهای از آن به صورت زیر است:
1function printName(firstName: string, lastName?: string) {
2if (lastName)
3 console.log(`Firstname: ${firstName}, Lastname: ${lastName}`);
4else console.log(`Firstname: ${firstName}`);
5}
در مثال فوق lastName یک پارامتر اختیاری است و معنی آن این است که در صورتی که در زمان فراخوانی تابع به آن اشاره نکنیم، کامپایلر خطایی صادر نخواهد کرد.
1printName('Gabriel', 'Tanner')
2printName('Gabriel')
این بدان معنی است که هر دو این حالتها صحیح تلقی میشوند.
مقادیر پیشفرض
متد دومی که میتوانیم برای ایجاد یک مشخصه اختیاری استفاده کنیم از طریق انتساب آن به یک مقدار پیشفرض است. این کار از طریق انتساب دادن مقدار مستقیماً به عنوان یک تابع میسر خواهد بود.
1function printName(firstName: string, lastName: string = 'Tanner') {
2 console.log(`Firstname: ${firstName}, Lastname: ${lastName}`);
3}
در این مثال، ما یک مقدار پیشفرض را به lastName انتساب دادهایم. معنی آن این است که نمیخواهیم آن را در هر بار فراخوانی تابع ارائه کنیم.
اینترفیسها
اینترفیسها در تایپاسکریپت برای تعریف قراردادهایی با خود کد و همچنین کد خارج از پروژه استفاده میشوند. اینترفیسها تنها شامل اعلانهایی از متدها و مشخصهها هستند، اما آنها را پیادهسازی نمیکنند. پیادهسازی متدها و مشخصهها در مسئولیت کلاسی است که اینترفیس را پیادهسازی میکند.
در ادامه نگاهی به مثالی از ساخت این گزارهها خواهیم داشت تا مسائل کمی روشنتر شوند:
1interface Person{
2 name: string
3}
4const person: Person = {name: 'Gabriel'}
5const person2: Person = {names: 'Gabriel'} // is not assignable to type Person
در کد فوق یک اینترفیس با یک مشخصه ایجاد میشود که باید در زمان پیادهسازی اینترفیس، پیادهسازی شود. به همین دلیل است که متغیر person دوم یک خطا ایجاد میکند.
مشخصههای اختیاری
در تایپاسکریپت همه مشخصههای یک اینترفیس الزامی نیستند. مشخصهها میتوانند با استفاده از عملگر ? پس از نام مشخصه به صورت اختیاری تعیین شوند.
1interface Person{
2 name: string
3 age?: number
4}
5const person: Person = {name: 'Frank', age: 28}
6const person2: Person = {name: 'Gabriel'}
در ادامه یک اینترفیس با یک مشخصه نرمال و یک مشخصه اختیاری ایجاد میکنیم که با استفاده از عملگر ? تعریف میشود. به همین دلیل است که هر دو مقداردهندههای person معتبر هستند.
مشخصههای فقط-خواندنی
برخی مشخصههای اینترفیس باید تنها هنگامی اصلاح شوند که شیء در وهله نخست ایجاد میشود. ما میتوانیم این کارکرد را از طریق قرار دادن کلیدواژه readonly قبل از نام مشخصه تعیین کنیم.
1interface Person{
2 name: string
3 readonly id: number
4 age?: number
5}
6const person: Person = {name: 'Gabriel', id: 3127831827}
7person.id = 200 // Cannot assign to id because it is readonly
در این مثال، مشخصه id فقط-خواندنی است و نمیتوان آن را پس از ایجاد شیء تغییر داد.
Barrels
Barrels امکان جمعبندی چند ماژول اکسپورت در یک ماژول منفرد سادهتر را فراهم میسازند. به این منظور کافی است یک فایل جدید ایجاد کنیم که ماژولهای چندگانه اکسپورت پروژه در آن قرار خواهند گرفت.
1export * from './person';
2export * from './animal';
3export * from './human';
پس از انجام این کار میتوانیم همه این ماژولها را با استفاده از یک گزاره منفرد import، در پروژه ایمپورت کنیم.
1import { Person، Animal، Human } from 'index';
ژنریکها
ژنریکها امکان ایجاد کامپوننتهایی را میدهند که با طیف گستردهای از نوعها منطبق هستند و اختصاص به یک نوع ندارند. بدین ترتیب کامپوننت ما open میشود و قابلیت استفاده مجدد پیدا میکند. اینک ممکن است کنجکاو شوید که چرا مستقیماً از یک نوع استفاده نمیکنیم که چند نوع منفرد برای کامپوننت ما ارائه کند. در ادامه به بررسی یک مثال میپردازیم تا این موقعیت را بهتر درک کنیم. ما میخواهیم یک تابع ساختگی ساده داشته باشیم که پارامتری که به آن تجزیه میشود را بازگشت دهد.
1function dummyFun(arg: any): any {
2 return arg;
3}
با این که any یک ژنریک است و هر نوعی که برای آرگومان ارسال شود قبول میکند، اما یک تفاوت بزرگ وجود دارد. در این روش ما اطلاعات نوع داده ارسالی و نوع بازگشتی تابع را از دست میدهیم. بنابراین در ادامه به بررسی روش پذیرش همه انواع و در عین حال حفظ اطلاعات در مورد نوع بازگشتی میپردازیم.
1function dummyFun<T>(arg: T): T {
2 return arg
3}
در کد فوق از یک پارامتر ژنریک T استفاده کردهایم و از این رو میتوانیم نوع متغیر را دریافت کرده و آن را در ادامه استفاده کنیم. همچنین میتوانیم از آن به عنوان پارامتر بازگشتی خود استفاده کنیم که به ما امکان میدهد نوع متناظر را در زمان بازبینی کد ببینیم.
مادیفایرهای دسترسی
مادیفایرهای دسترسی به کنترل دسترسپذیری اعضای کلاس میپردازند. تایپاسکریپت از سه نوع مادیفایر دسترسی به صورت public ،private و protected پشتیبانی میکند.
Public: اعضای عمومی یا Public بدون هیچ محدودیتی در همه جا در دسترس هستند. این مادیفایر یک مادیفایر استاندارد محسوب میشود، یعنی لازم نیست در زمان تعریف متغیرهای عمومی از کلیدواژه Public استفاده کنید.
Private: اعضای خصوصی تنها از درون کلاسی که در آن تعریف شدهاند قابل دسترسی هستند.
Protected: اعضای حفاظت شده میتوانند تنها از درون کلاسی که در آن تعریف شدهاند و همچنین کلاسهای فرعی و فرزند آن مورد دسترسی قرار گیرند.
TSLINT
TSLINT یک linter استاندارد برای تایپاسکریپت است و به نوشتن کدهای تمیز، قابل نگهداری و خوانا کمک میکند. آن را میتوانیم با قواعد lint، پیکربندی و قالببندیهای خاص که خودمان مینویسیم به صورت سفارشی درآوریم.
نصب TSLINT
ابتدا باید تایپاسکریپت و tslint را نصب کنیم و این کار به صورت محلی یا سراسری ممکن است:
npm install tslint typescript --save-dev npm install tslint typescript –g
پس از آن میتوانیم از TSLINT CLI برای مقداردهی اولیه TSLINT در پروژه خود استفاده کنیم:
tslint –init
اینک که فایل tslint.json خود را ساختیم، میتوانیم شروع به پیکربندی قواعد خاص خود بکنیم.
پیکربندی TSLINT
TSLINT امکان پیکربندی قواعد خاص و سفارشی روش نمایش کد را به ما میدهد. به صورت پیشفرض فایل tslint.json مانند زیر است و تنها قواعد پیشفرض در آن قرار دارند:
1{
2"defaultSeverity": "error",
3"extends": [
4 "tslint:recommended"
5],
6"jsRules": {},
7"rules": {},
8"rulesDirectory": []
9}
ما میتوانیم قواعد خود را با قرار دادن در شیء rules تعریف کنیم:
1"rules": {
2 "no-unnecessary-type-assertion": true,
3 "array-type": [true, "array"],
4 "no-double-space": true,
5 "no-var-keyword": true,
6 "semicolon": [true, "always", "ignore-bound-class-methods"]
7},
برای کسب اطلاعات بیشتر در مورد قواعد موجود میتوانید نگاهی به مستندات رسمی (+) آن بیندازید.
سخن پایانی
بدین ترتیب به پایان این مقاله میرسیم. امیدواریم مطالعه این راهنما به شما کمک کرده باشد که با مبانی تایپاسکریپت آشنا شوید و روش استفاده از آن در پروژهها را بدانید.
اگر این مطلب برای شما مفید بوده است، آموزشهای زیر نیز به شما پیشنهاد میشوند:
- مجموعه آموزشهای JavaScript (جاوا اسکریپت)
- آموزش JavaScript ES6 (جاوا اسکریپت)
- مجموعه آموزشهای برنامهنویسی
- 1۰ کتابخانه و فریمورک جاوا اسکریپت که باید آنها را بشناسید
- 12 نکته کلیدی برای ارزیابی کتابخانه های جدید جاوا اسکریپت
==
ممنون مختصر و عالی بود راحت اصل مطلب بیان شده توضیح اضافی هم نداره
مرسی، خیلی مختصر و مفید بود.