۹ ترفند جاوا اسکریپت که باید در سال ۲۰۱۹ بدانید — راهنمای کاربردی

۵۴ بازدید
آخرین به‌روزرسانی: ۰۸ شهریور ۱۴۰۲
زمان مطالعه: ۸ دقیقه
۹ ترفند جاوا اسکریپت که باید در سال ۲۰۱۹ بدانید — راهنمای کاربردی

جاوا اسکریپت نیز همچون هر زبان برنامه‌نویسی دیگری دائماً در حال تغییر است. در این مطلب، برخی از نکات و ترفندهای جالب برای نوشتن کد تمیز و کارآمد را در که سال 2019 به کار شما می‌آیند معرفی خواهیم کرد. در ادامه، فهرستی از 9 ترفند جالب جاوا اسکریپت معرفی شده است که شما را به توسعه‌دهنده بهتری تبدیل می‌کند.

1. async / await

اگر همچنان در جهنم Callback گیر کرده‌اید، دیگر نوبت آن است که آن را کنار بگذارید و دیگر از callback-ها استفاده نکنید، مگر این که مطلقاً ضروری باشد، یعنی از سوی یک کتابخانه الزام شده باشد یا دلایل عملکردی داشته باشد. Promise-ها مناسب هستند، اما اگر کد بیس شما بزرگ شود کمی دشوار خواهند بود. امروزه راه‌حل مناسب async / await است که باعث می‌شود خوانایی و بهبود کد تا حدود زیادی بیشتر شود.

در واقع، می‌توانید همه Promise-ها را در جاوا اسکریپت به صورت await تعریف کنید، اگر یکی از کتابخانه‌هایی که استفاده می‌کنید، یک Promise بازگشت می‌دهد، کافی است آن را await کنید. در واقع async/await صرفاً یک بازنویسی از Promise-ها محسوب می‌شود. برای این که کد کار کند، کافی است کلیدواژه async را به ابتدای تابع اضافه کنید. به مثال ساده زیر توجه کنید:

1async function getData() {
2    const result = await axios.get('https://dube.io/service/ping')
3    const data = result.data
4    
5    console.log('data', data)
6    
7    return data
8}
9
10getData()

توجه داشته باشید که استفاده از await در سطح فوقانی ممکن نیست و می‌توانید صرفاً یک تابع async فراخوانی کنید. async / await به همراه ES2017 معرفی شده است، بنابراین باید مطمئن شوید که کد خود را transpile می‌کنید.

2. گردش کنترل async

در اغلب موارد لازم است که چند دیتاست را واکشی کنید و روی هر کدام کار خاصی انجام دهید یا پس از این که همه فراخوانی‌های async کامل شدند مقداری را بازگشت دهید.

for…of

فرض کنید چند پوکمن روی صفحه خود داریم و می‌خواهیم اطلاعات تفصیلی در مورد آن‌ها به دست آوریم. ما قصد نداریم صبر کنیم تا همه فراخوانی‌ها به پایان برسند، به خصوص این که نمی‌دانیم چند تا از آن‌ها وجود دارند، بلکه می‌خواهیم مجموعه داده‌های خود را تا حد امکان در اولین فرصت ممکن به‌روزرسانی کنیم تا چیزی برای بازگشت دادن داشته باشیم. در این زمان می‌توانیم از حلقه for…of در یک آرایه استفاده کنیم و کد async را درون آن بلوک اجرا کنیم. بنابراین اجرای کد تا زمانی که همه فراخوانی‌ها با موفقیت بازگشت یابند متوقف می‌شود. لازم به ذکر است که اگر کاری شبیه به این در کد انجام دهید، ممکن است با افت عملکرد مواجه شوید، اما دسترسی به چنین ابزاری در کد بسیار مفید است. به مثال زیر توجه کنید:

1import axios from 'axios'
2
3let myData = [{id: 0}, {id: 1}, {id: 2}, {id: 3}]
4
5async function fetchData(dataSet) {
6    for(entry of dataSet) {
7        const result = await axios.get(`https://ironhack-pokeapi.herokuapp.com/pokemon/${entry.id}`)
8        const newData = result.data
9        updateData(newData)
10        
11        console.log(myData)
12    }
13}
14
15function updateData(newData) {
16    myData = myData.map(el => {
17        if(el.id === newData.id) return newData
18        return el
19    })
20}
21    
22fetchData(myData)

این مثال‌ها، در عمل کار می‌کنند، بنابراین می‌توانید آن‌ها را کپی کرده و در کدهای خود استفاده کنید.

Promise.all

اگر بخواهید همه پوکمن ها را به صورت موازی واکشی کنید، از آنجا که می‌توانید همه Promise-ها را await کنید، کافی است از Promise.all استفاده کنید:

1import axios from 'axios' 
2
3let myData = [{id: 0}, {id: 1}, {id: 2}, {id: 3}]
4
5async function fetchData(dataSet) {
6    const pokemonPromises = dataSet.map(entry => {
7        return axios.get(`https://ironhack-pokeapi.herokuapp.com/pokemon/${entry.id}`)
8    })
9
10    const results = await Promise.all(pokemonPromises)
11    
12    results.forEach(result => {
13        updateData(result.data)
14    })
15    
16    console.log(myData) 
17}
18
19function updateData(newData) {
20    myData = myData.map(el => {
21        if(el.id === newData.id) return newData
22        return el
23    })
24}
25    
26fetchData(myData)

for...of و Promise.all به همراه +ES6 معرفی شده‌اند، بنابراین باید مطمئن شوید که کد خود را transplie می‌کنید.

3. تجزیه و مقادیر پیش‌فرض

در این مرحله می‌خواهیم به مثال قبلی بازگردیم که کار زیر را انجام داده‌ایم:

const result = axios.get(`https://ironhack-pokeapi.herokuapp.com/pokemon/${entry.id}`)

const data = result.data

یک روش ساده‌تر نیز برای انجام این کار وجود دارد. ما می‌توانیم از تجزیه کد برای گرفتن برخی مقادیر از یک شیء یا یک آرایه استفاده کنیم. این کار به صورت زیر انجام می‌یابد:

const { data } = await axios.get(...)

ما یک خط کد صرفه‌جویی کرده‌ایم. همچنین می‌توانید نام متغیر خود را تغییر دهید:

const { data: newData } = await axios.get(...)

ترفند جالب دیگر این است که در زمان تجزیه مقادیر پیش‌فرض را ارائه کنیم. این وضعیت تضمین می‌کند که هرگز در انتها مقدار undefined نخواهید داشت و نیازی به بررسی دستی متغیرها وجود ندارد.

const { id = 5 } = {}

console.log(id) // 5

این ترفندها می‌توانند به همراه پارامترهای تابع استفاده شود. به مثال زیر توجه کنید:

1function calculate({operands = [1, 2], type = 'addition'} = {}) {
2    return operands.reduce((acc, val) => {
3        switch(type) {
4            case 'addition':
5                return acc + val
6            case 'subtraction':
7                return acc - val
8            case 'multiplication':
9                return acc * val
10            case 'division':
11                return acc / val
12        }
13    }, ['addition', 'subtraction'].includes(type) ? 0 : 1)
14}
15
16console.log(calculate()) // 3
17console.log(calculate({type: 'division'})) // 0.5
18console.log(calculate({operands: [2, 3, 4], type: 'multiplication'})) // 24

این مثال ممکن است در ابتدا کمی سردرگم‌کننده باشد؛ اما می‌توانید کمی وقت صرف کنید و با آن بیشتر آشنا شوید. زمانی که هیچ مقداری به عنوان آرگومان به تابع خود ارسال نمی‌کنیم، مقادیر پیش‌فرض مورد استفاده قرار می‌گیرند. به محض این که شروع به ارسال مقادیر می‌کنیم، تنها مقادیر پیش‌فرض برای آرگومان‌های ناموجود استفاده می‌شوند.

تجزیه و مقادیر پیش‌فرض به همراه ES6 معرفی شدند، بنابراین مطمئن شوید که کد خود را transpile می‌کنید.

4. مقادیر درست و نادرست

زمانی که از مقادیر پیش‌فرض استفاده می‌کنیم، برخی از بررسی‌ها برای مقادیر موجود متعلق به گذشته خواهند بود. با این حال، بهتر است بدانید که می‌توانید با مقادیر کار کنید. این امر موجب بهبود کد شما می‌شود و چند دستور صرفه‌جویی کرده و موجب گویاتر شدن کد می‌شود.

در اغلب موارد به صورت زیر عمل می‌کنیم:

1if(myBool === true) {
2  console.log(...)
3}
4// OR
5if(myString.length > 0) {
6  console.log(...)
7}
8// OR
9if(isNaN(myNumber)) {
10  console.log(...)
11}

همه این موارد می‌توانند به صورت اختصاری نوشته شوند:

1if(myBool) {
2  console.log(...)
3}
4// OR
5if(myString) {
6  console.log(...)
7}
8// OR
9if(!myNumber) {
10  console.log(...)
11}

برای بهره‌برداری از مزیت این گزاره‌ها باید درک کنید که مقادیر درست و نادرست کدام هستند. روش آن به صورت زیر توضیح داده می‌شود:

گزاره‌های نادرست

  • رشته‌هایی به طول 0
  • عدد 0
  • False
  • undefined
  • null
  • NaN

گزاره‌های درست

  • آرایه‌های خالی
  • اشیای خالی
  • همه چیزهای دیگر

توجه کنید که وقتی مقادیر درست/نادرست را بررسی می‌کنید، هیچ قیاس صریحی وجود ندارد که معادل بررسی با علامت تساوی دوگانه (==) و یا سه‌گانه (===) باشد. به طور کلی، طرز رفتار آن به همان روش است، اما موقعیت‌های خاصی هستند که در نهایت به باگ می‌رسند. در اغلب موارد این موضوع در مورد عدد 0 رخ می‌دهد.

5. عملگرهای منطقی و سه‌تایی

از این عملگرها نیز برای کوتاه کردن کد استفاده می‌شود و موجب صرفه‌جویی در خطوطی از کد می‌شود. در اغلب موارد ابزارهای جالبی وجود دارند که به پاکسازی کد کمک می‌کنند، اما ممکن است موجب ایجاد سردرگمی به خصوص در زمانی که به صورت زنجیره‌ای استفاده می‌شوند نیز بشوند.

عملگرهای منطقی

عملگرهای منطقی اساساً ترکیبی از دو عبارت هستند و مقدار true یا false بازگشت می‌دهند یا با یک مقدار مطابقت می‌یابند و به وسیله && یعنی «و» و همچنین || به معنی «یا» نمایش پیدا می‌کنند. به مثال زیر توجه کنید:

console.log(true && true) // true
console.log(false && true) // false
console.log(true && false) // false
console.log(false && false) // false
console.log(true || true) // true
console.log(true || false) // true
console.log(false || true) // true
console.log(false || false) // false

ما می‌توانیم عملگرهای منطقی را با دانشی که از نکته قبلی در مورد مقادیر درست و نادرست به دست آوریم ترکیب کنیم. زمانی که از عملگرهای منطقی استفاده می‌کنیم قواعد زیر صدق می‌کنند:

  • && - نخستین مقدار نادرست بازگشت می‌یابد، اگر چنین موردی نباشد، آخرین مقدار درست بازگشت خواهد یافت.
  • || - نخستین مقدار درست بازگشت می‌یابد، اگر چنین مقداری وجود نداشته باشد، عملیات معادل مقدار نادرست خواهد بود.
console.log(0 && {a: 1}) // 0
console.log(false && 'a') // false
console.log('2' && 5) // 5
console.log([] || false) // []
console.log(NaN || null) // null
console.log(true || 'a') // true

عملگر سه‌تایی

عملگر سه‌تایی بسیار شبیه به عملگر منطقی است؛ اما سه بخش دارد:

مقایسه که درست یا نادرست است.

  1. مقدار بازگشتی اول در حالت درست بودن ترکیب.
  2. مقدار بازگشتی دوم در حالت نادرست بودن ترکیب.

به مثال زیر توجه کنید:

const lang = 'German'
console.log(lang === 'German'? 'Hallo': 'Hello') // Hallo
console.log(lang? 'Ja': 'Yes') // Ja
console.log(lang === 'French'? 'Bon soir': 'Good evening') // Good evening

6. زنجیره‌سازی اختیاری

آیا تاکنون موقعیتی بوده است که لازم باشد به یک مشخصه شیء به صورت تودرتو و بدون دانستن این که آن شیء یا یکی از مشخصه‌های فرعی آن وجود دارند دسترسی پیدا کنید؟ در نهایت احتمالاً به چیزی مانند زیر رسیده‌اید:

let data

if(myObj && myObj.firstProp && myObj.firstProp.secondProp && myObj.firstProp.secondProp.actualData) data = myObj.firstProp.secondProp.actualData

این کد پیچیده است و روش بهتری برای نوشتن آن وجود دارد. این روش زنجیره‌سازی اختیاری نام دارد و طرز کار آن به صورت زیر است:

const data = myObj?.firstProp?.secondProp?.actualData

این یک روش گویا برای زنجیره‌سازی مشخصه‌های تودرتو است و موجب تمیزتر شدن کد می‌شود. در حال حاضر زنجیره‌سازی اختیاری بخشی از مشخصه‌های رسمی زبان نیست، اما در مرحله 1 قابلیت‌های آزمایشی قرار دارد.

7. مشخصه‌های کلاس و اتصال

اتصال تابع‌ها در جاوا اسکریپت کار مرسومی است. با معرفی تابع‌های arrow در نسخه ES6 اینک روشی برای اتصال خودکار تابع‌ها به «چارچوب اعلان» (Declare context) داریم که بسیار مفید است و به طور رایج از سوی توسعه‌دهندگان جاوا اسکریپت مورد استفاده قرار می‌گیرد. زمانی که کلاس‌ها نخستین بار معرفی شدند، دیگر نمی‌توانید عملاً از تابع‌های arrow استفاده کنید، زیرا متدهای کلاس باید به روش مشخصی اعلان شوند. در این زمان مجبور هستیم تابع‌ها را جای دیگری برای مثال در سازنده (که بهترین رویه در react.js محسوب می‌شود) اتصال دهیم.

اغلب توسعه‌دهندگان همیشه در زمینه گردش کار این مسئله که ابتدا متدهای کلاس را تعریف کنند و سپس آن‌ها را اتصال دهند دچار تعجب می‌شوند زیرا مسخره به نظر می‌رسد. با استفاده از ساختار مشخصه کلاس می‌توانید از تابع‌های arrow بار دیگر استفاده کنید و از مزیت اتصال خودکار بهره بگیرید. تابع‌های arrow می‌تواند درون کلاس استفاده شود. در ادامه مثالی از شیوه اتصال _increaseCount را ملاحظه می‌کنید:

1class Counter extends React.Component {
2    constructor(props) {
3        super(props)
4        this.state = { count: 0 }
5    }
6    
7    render() {
8        return(
9            <div>
10                <h1>{this.state.count}</h1>  
11                <button onClick={this._increaseCount}>Increase Count</button>
12            </div>
13        )
14    }
15    
16    _increaseCount = () => {
17        this.setState({ count: this.state.count + 1 })
18    }
19}

در حال حاضر، مشخصه‌های کلاس بخشی از مشخصه‌های رسمی زبان نیستند، اما در مرحله 3 قابلیت‌های آزمایشی قرار دارند.

8. استفاده از parcel

شما به عنوان یک توسعه‌دهنده فرانت‌اند، تقریباً به طور قطع تاکنون با مراحل بسته‌بندی و transpile کردن کد مواجه شده‌اید. استاندارد جاری برای این کار مدت‌ها است که استفاده از webpack بوده است. استفاده از نسخه 1 webpack کار دشواری محسوب می‌شد و نیازمند سروکله زدن با همه گزینه‌های مختلف پیکربندی و صرف ساعت‌ها وقت برای تلاش جهت بسته‌بندی و اجرا بود. اغلب کسانی که موفق به این کار می‌شدند از ترس از کار افتادن یک بخش، دیگر به آن دست نمی‌زدند.

اما روش راحت‌تری نیز برای این کار وجود دارد و آن استفاده از webpack است که بسیار آسان‌تر است. این کتابخانه تقریباً همه چیز را به صورت آماده در اختیار شما قرار می‌دهد و هر زمان در صورت نیاز می‌توانید تنظیمات را تغییر دهید. همچنین از سیستم افزونه نیز پشتیبانی می‌کند که از این نظر مشابه webpack یا babel است و عملکرد کاملاً سریعی نیز دارد. بنابراین پیشنهاد می‌کنیم حتماً آن را امتحان کنید.

9. خودتان بیشتر کد را بنویسید

این موضوع جالبی است و بحث‌های مختلف در مورد آن وجود دارد. حتی در مورد CSS اغلب افراد میل دارند که از یک کتابخانه کامپوننت مانند bootstrap استفاده کنند. در مورد جاوا اسکریپت افرادی را می‌بینیم که همچنان از jQuery و کتابخانه‌های کوچک دیگر برای اعتبارسنجی، اسلایدر و موارد دیگر استفاده می‌کنند. با این که استفاده از کتابخانه‌ها کار بدی نیست، اما بهتر است تلاش کنید خودتان کد بیشتری بنویسید تا این که پکیج‌های npm را به صورت کورکورانه نصب کنید. تنها زمانی معقول نیست خودتان کدنویسی کنید که کتابخانه‌های بزرگ و یا حتی فریمورک‌هایی مانند moment.js یا react-datepicker باشند که کل یک تیم مشغول ساخت آن هستند. با این حال شما در هر پروژه‌ای می‌توانید بیشتر کد موردنیاز را خودتان بنویسید. این کار چند مزیت دارد:

  1. از اتفاقاتی که در کد می‌افتند، دقیقاً مطلع خواهید بود.
  2. در نقطه‌ای از زمان شروع به درک واقعی برنامه‌نویسی خواهید کرد و با طرز کار همه چیز در پس‌زمینه به طور کامل آشنا می‌شوید.
  3. از حجیم‌تر شدن کدبیس خود جلوگیری می‌کنید.

در ابتدا بهتر است از یک پکیج npm استفاده کنید. پیاده‌سازی برخی کارکردها از سوی خودتان ممکن است به زمان زیادی نیاز داشته باشد؛ اما اگر پکیج دقیقاً مطابق انتظار کار نکند و بخواهید به پکیج دیگری بروید، بهتر است زمان بیشتری را صرف آشنایی با طرز کار API آن‌ها بکنید. زمانی که آن را خودتان پیاده‌سازی کنید، می‌توانید آن را صد در صد با نیازی که دارید مطابقت دهید.

اگر این مطلب برای شما مفید بوده است، آموزش‌های زیر نیز به شما پیشنهاد می‌شوند:

==

بر اساس رای ۰ نفر
آیا این مطلب برای شما مفید بود؟
اگر بازخوردی درباره این مطلب دارید یا پرسشی دارید که بدون پاسخ مانده است، آن را از طریق بخش نظرات مطرح کنید.
منابع:
gitconnected
نظر شما چیست؟

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *