گوگل برای دولوپرهایی که با اصول نوشتن کدهای تمیز و قابلفهم جاوااسکریپت آشنایی ندارند، دستورالعملی تحت عنوان Google JavaScript Style Guide منتشر نموده است (البته این دستورالعمل، قوانینی قطعی برای نوشتن کدهای معتبر را در بر نمیگیرد بلکه تنها شامل قوانین و رهنمودهایی برای ایجاد و حفظ سَبکی پایدار و زیبا در سورسکد است). با این تفاسیر، این دستورالعمل در مورد جاوااسکریپت که زبانی انعطافپذیر بوده و انتخاب گزینههای مختلفی از استایلها را امکانپذیر کرده است، اهمیت ویژهای پیدا میکند.
Google و Airbnb دو دستورالعمل کدنویسی JS منتشر نمودهاند که هر دوی آنها مورد استقبال قرار گرفتهاند. اگر کدنویسی JS یکی از مهمترین مشغلههای شما است، توصیه میکنیم که هر دوی این دستورالعملها را مطالعه کنید (مشاهدهٔ گایدلاینهای Airbnb در کدنویسی جاوااسکریپت). آنچه در ادامه میخوانید، ۱۳ مورد از مهمترین و جذابترین مواردی است که در دستورالعمل گوگل به آن اشاره شده است (از مباحث جنجالی و داغی مانند استفاده از Tab در مقابل استفاده از Space و نحوهٔ استفاده از Semicolon گرفته تا مباحثی که معمولاً زیاد مورد توجه قرار نمیگیرند).
در مورد هر یک از قوانین، ابتدا توضیح کوتاهی ارائه خواهد شد، سپس بخشی از دستورالعمل گوگل که در رابطه با آن قانون است بیان میشود. در موارد ضروری، مثالیهایی نیز ارائه شده و با نمونهای که قانون مورد نظر در آن رعایت نشده مورد مقایسه قرار گرفته است.
استفاده از Space به جای Tab
به غیر از Line Terminator Sequence، کاراکتر 0x20 تنها کاراکتر فضای سفید (Whitespace) است که در هر جایی از سورسکد میتواند ظاهر شود. این بدان معنا است که کاراکتر Tab نباید به منظور ایجاد تورفتگی در کدها مورد استفاده قرار گیرد. در دستورالعمل گوگل، بیان شده است که برای ایجاد تورفتگی در کدها، تنها از ۲ کاراکتر اسپیس (و نه ۴ تا) استفاده کنید:
// bad
function foo() {
∙∙∙∙let name;
}
// bad
function bar() {
∙let name;
}
// good
function baz() {
∙∙let name;
}
ضرورت استفاده از Semicolon
هر دستور یا اصطلاحاً Statement جاوااسکریپت، الزاماً باید با نقطهویرگول (Semicolon) پایان یابد. گوگل نیز در گایدلاین جاوااسکریپت خود بر لزوم استفاده از نقطهویرگول تأکید کرده است:
// bad
let luke = {}
let leia = {}
[luke, leia].forEach(jedi => jedi.father = 'vader')
// good
let luke = {};
let leia = {};
[luke, leia].forEach((jedi) => {
jedi.father = 'vader';
});
عدم استفاده از از ماژولهای ES6
از آنجا که ماژولهای ES6 (بهعنوان مثال کلیدواژههای export و import) هنوز نهایی نشدهاند، در حال حاضر نباید آنها را در کدهای جاوااسکریپت مورد استفاده قرار داد. بدیهی است که این دستورالعمل پس از استانداردسازی نهایی این ماژولها، مورد بازبینی قرار خواهد گرفت:
// Don't do this kind of thing yet:
//------ lib.js ------
export function square(x) {
return x * x;
}
export function diag(x, y) {
return sqrt(square(x) + square(y));
}
//------ main.js ------
import { square, diag } from 'lib';
Horizontal Alignment ممنوع نیست اما بهتر است انجام نشود
تراز کردن افقی خطوط (Horizontal Alignment)، عملی است که طی آن با افزودن فاصله قبل از مقدار یک متغیر، انتهای خط با خطوط بالایی و پایینی هماهنگ میشود. هرچند تراز کردن افقی خطوط مجاز است، اما در دستورالعمل گوگل انجام آن به شدت نهی شده است:
// bad
{
tiny: 42,
longer: 435,
};
// good
{
tiny: 42,
longer: 435,
};
عدم استفاده از کلیدواژهٔ var
تمام متغیرهای لوکال باید با کلیدواژههای const و let تعریف شوند. به طور پیشفرض، باید از const استفاده شود مگر این که قرار باشد مقدار متغیری قابلتغییر باشد (که در این صورت از let استفاده میشود):
// bad
var example = 42;
// good
let example = 42;
استفاده از <= به جای کلیدواژهٔ function
علامت <= علاوه بر اینکه ظاهر زیباتری دارد و سبب کوتاه و سادهتر شدن سینتکس میشود، برخی از مشکلات موجود در رابطه با کلیدواژهٔ function را نیز برطرف مینماید (به ویژه در مورد توابع تو در تو):
// bad
[1, 2, 3].map(function (x) {
const y = x + 1;
return x * y;
});
// good
[1, 2, 3].map((x) => {
const y = x + 1;
return x * y;
});
استفاده از Template Strings به جای Concatenation
به جای کانکَت (الحاق) استرینگهای متعدد، میتوانید آنها را به صورت اصطلاحاً Template String قرار گرفته داخل علامت ` بنویسید. لازم به ذکر است که Template String میتواند تا چندین خط طول داشته باشد:
// bad
function sayHi(name) {
return 'How are you, ' + name + '?';
}
// bad
function sayHi(name) {
return ['How are you, ', name, '?'].join();
}
// bad
function sayHi(name) {
return `How are you, ${ name }?`;
}
// good
function sayHi(name) {
return `How are you, ${name}?`;
}
عدم استفاده از Line Continuation برای استرینگهای طولانی
Line Continuation عملی است که در آن یک استرینگ طولانی به چند خط تقسیم شده و در انتهای هر یک از خطوط یک بکاِسلَش (\) قرار میگیرد. چه در استرینگهای معمولی و چه در استرینگهای تمپلیت، نباید از اصطلاحاً Line Continuation استفاده کرد. هرچند در ES5 مجاز دانسته شده است، اما این کار سبب کاهش خوانایی کد شده و علاوه بر این اگر پس از \ فضای خالی قرار بگیرد، ممکن است به ایجاد ارورهای گمراهکنندهای منجر شود!
گوگل توصیه کرده است که به جای استفاده از Line Continuation، استرینگ طولانی به صورت چند استرینگ کوتاهتر درآمده و به هم الحاق (Concatenate) شوند اما کمپانی Airbnb توصیه کرده است که هر چقدر هم یک استرینگ طولانی باشد، آن را دستکاری نکنید و به همان صورت طولانی رهایش کنید:
// bad (sorry, this doesn't show up well on mobile)
const longString = 'This is a very long string that \
far exceeds the 80 column limit. It unfortunately \
contains long stretches of spaces due to how the \
continued lines are indented.';
// good
const longString = 'This is a very long string that ' +
'far exceeds the 80 column limit. It does not contain ' +
'long stretches of spaces since the concatenated ' +
'strings are cleaner.';
استفاده از سینتکس for… of برای حلقهها
با استفاده از ES6، جاوااسکریپت دارای سه نوع حلقهٔ for است. استفاده از هر سه نوع آن مجاز است اما بر اساس دستورالعمل گوگل، بهتر است که استفاده از حلقهٔ for ... of در اولویت قرار بگیرد.
عدم استفاده از فانکشن ()eval
از تابع ()eval تا حد ممکن استفاده نکنید چرا که این دست فیچرها به طور بالقوهای خطرناک بوده و به ویژه در محیطهای CSP کارایی ندارند (CSP مخفف واژگان Communicating Sequential Processes میباشد که نشانگر یکسری الگو در سیستمهای به اصطلاح کانکارنت میباشد):
// bad
let obj = { a: 20, b: 30 };
let propName = getPropName(); // returns "a" or "b"
eval( 'var result = obj.' + propName );
// good
let obj = { a: 20, b: 30 };
let propName = getPropName(); // returns "a" or "b"
let result = obj[ propName ]; // obj[ "a" ] is the same as obj.a
لزوم نوشتن نام کانستنتها به حروف بزرگ
نام کانستنتها (ثابتها) باید به طور کامل با حروف بزرگ نوشته شود و بخشهای مختلف آن با استفاده از Underscore یا _ از یکدیگر جدا شوند. اگر مطمئن هستید که مقدار ثابتی که تعریف نمودهاید دیگر تغییر نخواهد کرد، میتوانید نام آن را با حروف بزرگ بنویسید و به این صورت نشان دهید که این مقدار در سرتاسر کد ثابت است و بدون تغییر باقی خواهد ماند.
یکی از استثنائات این قانون هنگامی است که کانستنتی برای استفاده در درون یک فانکشن تعریف شده و خارج از آن کاربردی ندارد؛ که در این صورت باید نام آن به صورت اصطلاحاً camelCase نوشته شود (یعنی نخستین حرف بخش دوم نام با حرف بزرگ نوشته شود):
// bad
const number = 5;
// good
const NUMBER = 5;
دیکلر کردن هر متغیر به صورت مجزا
هر متغیر لوکال را در یک Declaration (اعلان) جداگانه تعریف کنید و از تعریف چند متغیر در یک خط و پشت سر هم خودداری نمایید:
// bad
let a = 1, b = 2, c = 3;
// good
let a = 1;
let b = 2;
let c = 3;
استفاده از ' به جای "
در استرینگهای معمولی به جای " از ' استفاده میشود. اگر خود استرینگ در میان کوتیشن تکی (') قرار گرفته است، میتوان به جای حذف کوتیشن، استرینگ را به صورت تمپلیت نوشت:
// bad
let directive = "No identification of self or mission."
// bad
let saying = 'Say it ain\u0027t so.';
// good
let directive = 'No identification of self or mission.';
// good
let saying = `Say it ain't so`;
سخن پایانی
همانطور که در ابتدا گفتیم، اینها فقط توصیههای گوگل (به عنوان یکی از غولهای فناوری) است و الزامی بر رعایت آنها وجود ندارد اما از آنجا که شرکتهای بزرگ فناوری مانند گوگل، فیسبوک و غیره دولوپرهای برجسته و ماهر بسیاری را در استخدام خود دارند و این افراد ساعتها وقت صرف میکنند و برای این شرکتها کدهای عالی مینویسند، معمولاً توصیه میشود که دستورالعملهای این شرکتها در حین کدنویسی مد نظر قرار گیرند.