۱۹ تکنیک خلاصه نویسی JavaScript
استفاده از کدهای جاوا اسکریپت کاربرد فراوانی دارد، اما آیا میدانستید که خلاصه نویسی JavaScript برای برخی کدهای کاربردی وجود دارد که میتوانید زمان و فضای کمتری برای نوشتن آنها اختصاص دهید؟ در اینجا به معرفی برخی از کاربردیترین این کدها میپردازیم.
مقاله مرتبط: راهنمای غیر فعال کردن JavaScript در مرورگر های مختلف
آشنایی با این نکات برای هر توسعه گری که با جاوا اسکریپت کار میکند ضروری است. هدف ما از این مقاله ارائه منبعی مهم در یادگیری تکنیکهای کد نویسی کوتاه شده (Shorthand) است که در طول سالهای اخیر جمعآوری کردهایم. برای فهم بهتر آنچه در اینجا ارائهشده، نسخه بلند این کدها را هم آوردهایم تا دیدگاه کد نویسی آن را بهتر درک کنید.این مقاله برای راهنمایی هایی کوتاه بر اساس ES6 نوشته شده است.
۱. عملگر شرطی ( سه جانبه)
این مورد از بهترین تکنیک های خلاصه نویسی است، خصوصاً اگر بخواهید یک دستور if..else را در یک خط بنویسید.
نسخه بلند:
const x = ۲۰;
let answer;
if (x > ۱۰) {
answer = 'greater than 10';
} else {
answer = 'less than 10';
}
نسخه کوتاه شده:
const answer = x > ۱۰ ? 'greater than 10' : 'less than 10';
دستور if را میتوانید به شکل زیر هم قرار دهید:
const answer = x > ۱۰ ? " greater than 10" : x
۲. دستور کوتاه شده ارزیابی مدار کوتاه (&& و ||)
وقتی یک مقدار متغیر را برای یک متغیر دیگر تعیین میکنید، بهتر است مطمئن شوید که متغیر منبع بدون مقدار، تعریفنشده یا خالی نباشد. میتوانید یک دستور if بلند با چند عبارت شرطی بنویسید، هم میتوانید از یک ارزیابی مدار کوتاه استفاده کنید.
مقاله مرتبط: چگونه پیام هشدار واکنش گرا را جایگزین JavaScript کنیم؟
نسخه بلند:
if (variable1 !== null || variable1 !== undefined || variable1 !== '') {
let variable2 = variable1;
}
نسخه کوتاه شده:
const variable2 = variable1 || 'new';
باور ندارید؟ خودتان امتحان کنید. کد زیر را در es6console قرار دهید:
let variable1;
let variable2 = variable1 || '';
console.log(variable2 === ''); // prints true
variable1 = 'foo';
variable2 = variable1 || '';
console.log(variable2); // prints foo
۳. تعریف متغیر ها به صورت گروهی
بد نیست تعریف تخصیص متغیرهایتان را در ابتدای دستورها قرار دهید. این روش کوتاه شده زمانی که بخواهید چند متغیر را بهطور همزمان تعریف کنید میتواند در صرفهجویی زمان و فضا به شما کمک کند.
نسخه بلند:
let x;
let y;
let z = ۳;
نسخه کوتاه شده:
let x, y, z=۳;
۴. خلاصه نویسی دستور if
شاید چیز جزئی باشد اما ارزش دانستن دارد. وقتی “if checks” انجام میدهید، گاهی عملگرهای تخصیص را میتواند حذف کرد.
نسخه بلند:
if (likeJavaScript === true)
کوتاه شده:
if (likeJavaScript)
تذکر: این دو مثال کاملاً یکسان نیستند چون check کوتاه شده، تا وقتیکه likeJavaScript یک مقدار حقیقی باشد ادامه خواهد داشت.
یک مثال دیگر. اگر “a” با حقیقت برابر نباشد، کاری انجام بده:
نسخه بلند:
let a;
if ( a !== true ) {
// do something...
}
کوتاه شده:
let a;
if ( !a ) {
// do something...
}
۵. خلاصه نویسی حلقه (Loop)
اگر یک جاوا اسکریپت ساده بخواهید که روی کتابخانههای خارجی مانند jQuery یا lodash تکیه نکند، این نکته کوچک بسیار کاربردی خواهد بود.
نسخه بلند:
for (let i = ۰; i < allImgs.length; i++)
کوتاه شده:
for (let index of allImgs)
کوتاه شده برای Array.forEach:
function logArrayElements(element, index, array) {
console.log("a[" + index + "] = " + element);
}
[۲, ۵, ۹].forEach(logArrayElements);
// logs:
// a[0] = 2
// a[1] = 5
// a[2] = 9
۶. ارزیابی مدار کوتاه
وقتی یک پارامتر موردنظر بیمقدار باشد یا تعریفنشده باشد، بجای اینکه ۶ خط کد بنویسید تا یک مقدار پیشفرض را مشخص کنید میتوانید همان کار را بهراحتی با استفاده از یک عملگر منطقی مدار کوتاه در یک خط انجام دهید.
نسخه بلند:
let dbHost;
if (process.env.DB_HOST) {
dbHost = process.env.DB_HOST;
} else {
dbHost = 'localhost';
}
کوتاه شده:
const dbHost = process.env.DB_HOST || 'localhost';
۷. توانهای ده
شاید این مورد را قبلاً دیده باشید. در اصل یکراه خاص برای نوشتن اعداد بدون مقدار زیادی صفر است. برای مثال ۱e7 برابر است با عدد ۱ و ۷ صفر جلوی آن. درواقع نمادی دهدهی از عدد ۱۰۰۰۰۰۰۰ است (که جاوا اسکریپت بهعنوان یک نوع شناور میشناسد).
نسخه بلند:
for (let i = ۰; i < ۱۰۰۰۰; i++) {}
کوتاه شده:
for (let i = ۰; i < ۱e7; i++) {}
// All the below will evaluate to true
۱e0 === ۱;
۱e1 === ۱۰;
۱e2 === ۱۰۰;
۱e3 === ۱۰۰۰;
۱e4 === ۱۰۰۰۰;
۱e5 === ۱۰۰۰۰۰
۸. خلاصه نویسی ویژگی های object
تعریف object literals در جاوا اسکریپت زندگی را آسان میکند. ES6 راهی آسانتر را برای تخصیص ویژگیها به یک object فراهم کرده است. اگر نام ویژگی با اسم اصلی یکسان باشد، میتوانید از دستور کوتاه شده استفاده کنید.
نسخه بلند:
const obj = { x:x, y:y };
کوتاه شده:
const obj = { x, y };
۹. توابع Arrow کوتاه شده
خواندن و نوشتن توابع کلاسیک در قالب سادهشان بسیار راحت است، اما وقتی میخواهید آنها را در فراخوانیهای تابع دیگر اعمال کنید پیچیدهتر و طولانیتر میشوند.
نسخه بلند:
function sayHello(name) {
console.log('Hello', name);
}
setTimeout(function() {
console.log('Loaded')
}, ۲۰۰۰);
list.forEach(function(item) {
console.log(item);
});
کوتاه شده:
sayHello = name => console.log('Hello', name);
setTimeout(() => console.log('Loaded'), ۲۰۰۰);
list.forEach(item => console.log(item));
حتماً دقت کنید که مقدار this در یک تابع arrow برای نسخه کامل توابع به شکلی متفاوت تعیین میشود، درنتیجه این دو مثال کاملاً یکسان نیستند.
۱۰. دستور کوتاه شده برگشت ضمنی
برگشت کلیدواژهای است که اکثراً برای برگشت به نتیجه نهایی یک تابع استفاده میکنیم. یک تابع arrow که فقط یک دستور دارد، نتیجه ارزیابیاش را بهطور ضمنی برگشت میدهد (تابع باید آکلادها ({}) را حذف کند تا بتواند دستور برگشت را لغو کند).
برای برگشت دادن یک دستور چندخطی (مانند یک شیء لیترال)، باید در دو طرف تابع خود بجای {} از () استفاده کنید. بهاینترتیب مطمئن میشوید که این کد بهعنوان یک دستور واحد ارزیابی میشود.
نسخه کامل:
function calcCircumference(diameter) {
return Math.PI * diameter
}
کوتاه شده:
calcCircumference = diameter => (
Math.PI * diameter;
)
۱۱. مقادیر پارامتر پیشفرض
میتوانید از دستور if جهت تعیین مقادیر پیشفرض برای پارامترهای تابع استفاده کنید. در ES6، میتوانید مقادیر پیشفرض در همان تعریف تابع را تعیین کنید.
نسخه بلند:
function volume(l, w, h) {
if (w === undefined)
w = ۳;
if (h === undefined)
h = ۴;
return l * w * h;
}
کوتاه شده:
volume = (l, w = ۳, h = ۴ ) => (l * w * h);
volume(۲) //output: 24
۱۲. Template Literals
شما هم از اینکه برای الصاق چند متغیر به یکرشته از ‘ + ‘ استفاده کنید خسته شدهاید؟ راحت سادهتری برای این کار نیست؟ اگر میتوانید با ES6 کارکنید، شانس با شماست. تنها کافی است از علامت (“) استفاده کنید و علامت ${} را برای بستن متغیرهایتان بکار برید.
نسخه بلند:
const welcome = 'You have logged in as ' + first + ' ' + last + '.'
const db = 'http://' + host + ':' + port + '/' + database;
کوتاه شده:
const welcome = `You have logged in as ${first} ${last}`;
const db = `http://${host}:${port}/${database}`;
۱۳. کوتاه شدهٔ Destructuring Assignment
اگر با هر یک از فریم ورکهای محبوب وب کار میکنید، بهاحتمالزیاد از array ها یا دیتا در قالب لیترال های شیء برای انتقال اطلاعات بین اجزا و API ها استفاده میکنید. وقتیکه دیتای شیء به یکی از اجزا میرسد، باید آن را بازکنید.
نسخه بلند:
const observable = require('mobx/observable');
const action = require('mobx/action');
const runInAction = require('mobx/runInAction');
const store = this.props.store;
const form = this.props.form;
const loading = this.props.loading;
const errors = this.props.errors;
const entity = this.props.entity;
کوتاه شده:
import { observable, action, runInAction } from 'mobx';
const { store, form, loading, errors, entity } = this.props;
حتی میتوانید اسم متغیرها را بهدلخواه تعیین کنید:
const { store, form, loading, errors, entity:contact } = this.props;
۱۴. رشته چندخطی
اگر تابهحال پیشآمده که بخواهید رشتههای چندخطی را با کد بنویسید، به این شکل باید بنویسید:
نسخه بلند:
const lorem = 'Lorem ipsum dolor sit amet, consectetur\n\t'
+ 'adipisicing elit, sed do eiusmod tempor incididunt\n\t'
+ 'ut labore et dolore magna aliqua. Ut enim ad minim\n\t'
+ 'veniam, quis nostrud exercitation ullamco laboris\n\t'
+ 'nisi ut aliquip ex ea commodo consequat. Duis aute\n\t'
+ 'irure dolor in reprehenderit in voluptate velit esse.\n\t'
اما راه آسانتری هم وجود دارد. کافی است از (“) استفاده کنید.
کوتاه شده:
const lorem = `Lorem ipsum dolor sit amet, consectetur
adipisicing elit, sed do eiusmod tempor incididunt
ut labore et dolore magna aliqua. Ut enim ad minim
veniam, quis nostrud exercitation ullamco laboris
nisi ut aliquip ex ea commodo consequat. Duis aute
irure dolor in reprehenderit in voluptate velit esse.`
۱۵. عملگر گسترش (spread operator)
عملگر گسترش که در ES6 معرفی شد، کاربردهای متعددی دارد که استفاده از کد جاوا اسکریپت را کارآمدتر و جالبتر میکند. از آن میتوان برای جایگزین کردن برخی توابع array استفاده کرد. عملگر گسترش فقط شامل چند سهنقطه است.
نسخه بلند:
// joining arrays
const odd = [۱, ۳, ۵];
const nums = [۲ ,۴ , ۶].concat(odd);
// cloning arrays
const arr = [۱, ۲, ۳, ۴];
const arr2 = arr.slice()
کوتاه شده:
// joining arrays
const odd = [۱, ۳, ۵ ];
const nums = [۲ ,۴ , ۶, ...odd];
console.log(nums); // [ ۲, ۴, ۶, ۱, ۳, ۵ ]
// cloning arrays
const arr = [۱, ۲, ۳, ۴];
const arr2 = [...arr];
برخلاف تابع concat() میتوانید از عملگر گسترش برای واردکردن یک array به داخل هر array دیگر استفاده کنید.
const odd = [۱, ۳, ۵ ];
const nums = [۲, ...odd, ۴ , ۶];
همچنین میتوانید عملگر گسترش را با نشانهگذاری ES6 destructuring ترکیب کنید.
const { a, b, ...z } = { a: ۱, b: ۲, c: ۳, d: ۴ };
console.log(a) // ۱
console.log(b) // ۲
console.log(z) // { c: 3, d: 4 }
۱۶. پارامترهای اجباری
اگر در جاوا اسکریپت مقداری برای پارامترهای تابع مشخص نکرده باشید، بهطور پیشفرض آنها را indefined تعیین میکند. برخی زبانهای کد نویسی دیگر یک هشدار یا خطا نمایش میدهند. برای اعمال اجباری تخصیص پارامترها، میتوانید از دستور if برای نمایش خطا در صورت undefined بودن استفاده کنید، و یا میتوانید از دستور کوتاه شده پارامتر اجباری استفاده کنید.
نسخه بلند:
function foo(bar) {
if(bar === undefined) {
throw new Error('Missing parameter!');
}
return bar;
}
کوتاه شده:
mandatory = () => {
throw new Error('Missing parameter!');
}
foo = (bar = mandatory()) => {
return bar;
}
۱۷. دستور کوتاه شده Array.find
اگر تابهحال یک دستور find در یک جاوا اسکریپت ساده نوشته باشید، احتمالاً از یک حلقه for استفاده کردهاید. در ES6، یک تابع array جدید به نام find() معرفیشده است.
نسخه بلند:
const pets = [
{ type: 'Dog', name: 'Max'},
{ type: 'Cat', name: 'Karl'},
{ type: 'Dog', name: 'Tommy'},
]
function findDog(name) {
for(let i = ۰; i<pets.length; ++i) {
if(pets[i].type === 'Dog' && pets[i].name === name) {
return pets[i];
}
}
}
کوتاه شده:
pet = pets.find(pet => pet.type ==='Dog' && pet.name === 'Tommy');
console.log(pet); // { type: 'Dog', name: 'Tommy' }
۱۸. دستور خلاصه [Object key]
آیا میدانستید که Foo.bar را میتوانید مانند Foo[‘bar’] هم بنویسید؟ در ابتدا خیلیها نمیدانستند استفاده از این روش نوشتن چه لزومی میتواند داشته باشد. اما این نشانهگذاری اولین گام برای نوشتن کدهای قابلاستفاده مجدد را برایتان فراهم میکند.
برای مثال این نمونه سادهشده از یک تابع اعتبارسنجی را میبینید:
function validate(values) {
if(!values.first)
return false;
if(!values.last)
return false;
return true;
}
console.log(validate({first:'Bruce',last:'Wayne'})); // true
این تابع کارش را به نحو احسن انجام میدهد. اما حالتی را فرض کنید که فرمهای متعددی برای اعمال اعتبارسنجی دارید، اما هر یک در حوزهای متفاوت با قوانین متفاوتی هستند. بهتر نیست یک تابع اعتبارسنجی کلی بسازید که بتواند در هنگام اجراشدن تنظیم شود؟
نسخه کوتاه شده:
// object validation rules
const schema = {
first: {
required:true
},
last: {
required:true
}
}
// universal validation function
const validate = (schema, values) => {
for(field in schema) {
if(schema[field].required) {
if(!values[field]) {
return false;
}
}
}
return true;
}
console.log(validate(schema, {first:'Bruce'})); // false
console.log(validate(schema, {first:'Bruce',last:'Wayne'})); // true
اکنون یک تابع اعتبارسنجی داریم که میتوانیم در همه فرمها استفاده کنیم، بدون اینکه بخواهیم یک تابع اعتبارسنجی اختصاصی را برای تکتک آنها بنویسیم.
۱۹. نسخه کوتاه شده Double Bitwise NOT
عملگرهای بیتی (Bitwise) یکی از ویژگیهایی هستند که در راهنماهای مبتدی جاوا اسکریپت میآموزید اما هیچوقت آنها را درجایی اجرا نمیکنید. علاوه بر این، وقتی با سیستم دودویی سروکار ندارید چرا باید بخواهید با صفر و یک کارکنید؟
اما در حقیقت یکی از راههای کاربردی در عملگر بیتی دوتایی است. میتوانید آن را بهعنوان جایگزین Math.floor() استفاده کنید. مزیت عملگر Double Bitwise NOT این است که همان کار را سریعتر انجام میدهد.
نسخه بلند:
Math.floor(۴.۹) === ۴ //true
کوتاه شده:
~~۴.۹ === ۴ //true