Skip to content

راهنمای سبک جاوا اسکریپت | JavaScript Style Guide

License

Notifications You must be signed in to change notification settings

abolfazlchaman/javascript-style-guide

 
 

Repository files navigation

مخزن اصلی: airbnb/javascript

راهنمای سبک جاوا اسکریپت ()Airbnb {

یک رویکرد عمدتاً معقول برای جاوا اسکریپت

نکته: این راهنما فرض می کند که شما در حال استفاده از Babel هستید، و مستلزم این است که از babel-preset-airbnb یا معادل آن استفاده کنید. این راهنما همچنین فرض می‌کند که در حال استفاده از shims/polyfills در برنامه خود هستید, به همراه airbnb-browser-shims یا معادل آن.

سایر راهنماها:

فهرست مطالب

  1. انواع داده ها
  2. مراجع
  3. اشیاء
  4. آرایه ها
  5. استخراج(Destructuring)
  6. رشته ها
  7. توابع
  8. توابع پیکانی
  9. کلاس ها و سازندگان
  10. ماژول ها
  11. تکرار کننده ها و مولدها
  12. خصوصیات
  13. متغیرها
  14. بالا بردن
  15. اپراتورهای مقایسه و برابری
  16. بلوک ها
  17. بیانیه های کنترلی
  18. توضیح نویسی
  19. فضای سفید
  20. ویرگول ها
  21. نقطه ویرگول ها
  22. نوع ریختگی و اجبار
  23. قراردادهای نامگذاری
  24. دسترسی گیرنده / دهنده ها
  25. رویدادها
  26. جی کوئری
  27. سازگاری با ECMAScript 5
  28. سبک های ECMAScript 6+ (ES 2015+)
  29. کتابخانه استاندارد
  30. آزمایش کردن
  31. کارایی
  32. منابع
  33. موارد استفاده در دنیای واقعی
  34. ترجمه
  35. راهنمای راهنمای سبک جاوا اسکریپت
  36. درباره جاوا اسکریپت با ما گپ بزنید
  37. مشارکت کنندگان
  38. مجوز
  39. اصلاحیه ها

انواع داده ها

  • 1.1 نوع اولیه ها: هنگامی که به یک نوع اولیه دسترسی دارید، مستقیماً روی مقدار آن کار کنید.

  • string

  • number

  • boolean

  • null

  • undefined

  • symbol

  • bigint


    const foo = 1;
    let bar = foo;

    bar = 9;

    console.log(foo, bar); // => 1, 9

نمی توان به طرز درستی Symbols و BigInts ها را polyfill کرد، بنابراین نباید هنگام هدف قرار دادن مرورگرها/محیط هایی که به صورت بومی از آنها پشتیبانی نمی کنند استفاده شوند.

  • 1.2 انواع پیچیده: هنگامی که به یک نوع پیچیده دسترسی پیدا می کنید، با یک مرجع به مقدار آن کار کنید.

  • object

  • array

  • function


    const foo = [1, 2];
    const bar = foo;

    bar[0] = 9;

    console.log(foo[0], bar[0]); // => 9, 9

⬆ بازگشت به بالا

مراجع

  • 2.1 از const برای همه مراجع خود استفاده کنید; از استفاده از var اجتناب کنید.
    eslint: prefer-const, no-const-assign

    چرا؟ این کار تضمین می کند که نتوانید مراجع خود را مجدداً اختصاص دهید، که این کار می تواند منجر به اشکالات و درک کد دشوارتر شود.

    // ‎بد
    var a = 1;
    var b = 2;

    // ‎خوب
    const a = 1;
    const b = 2;

  • 2.2 اگر باید مراجع را دوباره اختصاص دهید, از let به جای var استفاده کنید. eslint: no-var

    چرا؟ let به جای محدوده تابعی مانند var دارای محدوده بلوکی است.

    // ‎بد
    var count = 1;
    if (true) {
      count += 1;
    }

    // ‎خوب،از let استفاده کنید
    let count = 1;
    if (true) {
      count += 1;
    }

  • 2.3 توجه داشته باشید که هر دو let و const دارای محدوده بلوکی هستند، در حالی که var دارای محدوده تابعی است.
    // ‎const و let فقط در بلوک هایی که در آنها تعریف شده اند وجود دارند.
    {
      let a = 1;
      const b = 1;
      var c = 1;
    }
    console.log(a); // ReferenceError
    console.log(b); // ReferenceError
    console.log(c); // Prints 1

در کد بالا، می‌بینید که ارجاع a و b یک ReferenceError ایجاد می‌کند، در حالی که c حاوی عدد است. این به این دلیل است که a و b دارای محدوده بلوکی هستند، در حالی که c به تابع حاوی آن محدوده است.

⬆ بازگشت به بالا

اشیاء

  • 3.1 از literal syntax برای ایجاد شیء ها استفاده کنید. eslint: no-new-object
    // ‎بد
    const item = new Object();

    // ‎خوب
    const item = {};

  • 3.2 هنگام ایجاد اشیایی با ویژگی های پویا از نام های ویژگی محاسبه شده استفاده کنید.

    چرا؟ این کار به شما اجازه می دهند تمام خصوصیات یک شیء را در یک مکان تعریف کنید.

    function getKey(k) {
      return `a key named ${k}`;
    }

    // ‎بد
    const obj = {
      id: 5,
      name: 'San Francisco',
    };
    obj[getKey('enabled')] = true;

    // ‎خوب
    const obj = {
      id: 5,
      name: 'San Francisco',
      [getKey('enabled')]: true,
    };

    // ‎بد
    const atom = {
      value: 1,

      addValue: function (value) {
        return atom.value + value;
      },
    };

    // ‎خوب
    const atom = {
      value: 1,

      addValue(value) {
        return atom.value + value;
      },
    };

  • 3.4 از کوتاه نویسی استفاده کنید. eslint: object-shorthand

    چرا؟ مختصرتر و توصیف کننده تر است.

    const lukeSkywalker = 'Luke Skywalker';

    // ‎بد
    const obj = {
      lukeSkywalker: lukeSkywalker,
    };

    // ‎خوب
    const obj = {
      lukeSkywalker,
    };

  • 3.5 کوتاه نویسی های خود را در ابتدای اعلان شیء گروه بندی کنید.

    چرا؟ تشخیص اینکه کدام خصوصیات شیء از کوتاه نویسی استفاده می کنند آسان تر است.

    const anakinSkywalker = 'Anakin Skywalker';
    const lukeSkywalker = 'Luke Skywalker';

    // ‎بد
    const obj = {
      episodeOne: 1,
      twoJediWalkIntoACantina: 2,
      lukeSkywalker,
      episodeThree: 3,
      mayTheFourth: 4,
      anakinSkywalker,
    };

    // ‎خوب
    const obj = {
      lukeSkywalker,
      anakinSkywalker,
      episodeOne: 1,
      twoJediWalkIntoACantina: 2,
      episodeThree: 3,
      mayTheFourth: 4,
    };

  • 3.6 فقط ویژگی هایی را داخل کوتیشن بگذارید که شناسه های نامعتبر هستند. eslint: quote-props

    چرا؟ به طور کلی ما خواندن آن را به صورت ذهنی ساده تر می دانیم.این کار برجسته سازی کد را بهبود می بخشد و همچنین توسط بسیاری از موتورهای جاوا اسکریپتی به راحتی بهینه می شود.

    // ‎بد
    const bad = {
      'foo': 3,
      'bar': 4,
      'data-blah': 5,
    };

    // ‎خوب
    const good = {
      foo: 3,
      bar: 4,
      'data-blah': 5,
    };

  • 3.7 هیچوقت Object.prototype را مستقیماً فراخوانی نکنید , مثلا hasOwnProperty, propertyIsEnumerable, و isPrototypeOf.
    eslint: no-prototype-builtins

    چرا؟ این متدها ممکن است با ویژگی‌های شیء مورد نظر تداخل داشته باشند - { hasOwnProperty: false } را در نظر بگیرید - یا شی، ممکن است یک شی، تهی باشد (Object.create(null)).

    // ‎بد
    console.log(object.hasOwnProperty(key));

    // ‎خوب
    console.log(Object.prototype.hasOwnProperty.call(object, key));

    // ‎بهترین
    const has = Object.prototype.hasOwnProperty; // ‎جستجو را یک بار در محدوده ماژول کش کنید.
    console.log(has.call(object, key));
    /*‎ یا ‎*/
    import has from 'has'; // https://www.npmjs.com/package/has
    console.log(has(object, key));
    /*‎ یا ‎*/
    console.log(Object.hasOwn(object, key)); // https://www.npmjs.com/package/object.hasown

  • 3.8 برای کپی کردن اشیاء Object.assign سینتکس گسترش شیء را ترجیح دهید. از سینتکس گسترش شیء استفاده کنید تا یک شیء جدید با ویژگی های خاصی حذف شده باشد. eslint: prefer-object-spread
    // ‎خیلی بد
    const original = { a: 1, b: 2 };
    const copy = Object.assign(original, { c: 3 }); // ‎این `اصلی` را تغییر می دهد ಠ_ಠ
    delete copy.a; // ‎همینطور این کار

    // ‎بد
    const original = { a: 1, b: 2 };
    const copy = Object.assign({}, original, { c: 3 }); // copy => { a: 1, b: 2, c: 3 }

    // ‎خوب
    const original = { a: 1, b: 2 };
    const copy = { ...original, c: 3 }; // copy => { a: 1, b: 2, c: 3 }

    const { a, ...noA } = copy; // noA => { b: 2, c: 3 }

⬆ بازگشت به بالا

آرایه ها

    // ‎بد
    const items = new Array();

    // ‎خوب
    const items = [];

  • 4.2 به جای انتساب مستقیم برای افزودن آیتم ها به یک آرایه از Array.push استفاده کنید.
    const someStack = [];

    // ‎بد
    someStack[someStack.length] = 'abracadabra';

    // ‎خوب
    someStack.push('abracadabra');

  • 4.3 برای کپی کردن آرایه ها از ... گسترش آرایه استفاده کنید.
    // ‎بد
    const len = items.length;
    const itemsCopy = [];
    let i;

    for (i = 0; i <br len; i += 1) {
      itemsCopy[i] = items[i];
    }

    // ‎خوب
    const itemsCopy = [...items];

  • 4.4 برای تبدیل یک شیء تکرارپذیر به آرایه, از اسپرد ... به جای Array.from استفاده کنید.
    const foo = document.querySelectorAll('.foo');

    // ‎خوب
    const nodes = Array.from(foo);

    // ‎بهترین
    const nodes = [...foo];

  • 4.5 برای تبدیل یک شیء آرایه مانند به یک آرایه از Array.from استفاده کنید.
    const arrLike = { 0: 'foo', 1: 'bar', 2: 'baz', length: 3 };

    // ‎بد
    const arr = Array.prototype.slice.call(arrLike);

    // ‎خوب
    const arr = Array.from(arrLike);

  • 4.6 برای نگاشت روی تکرارپذیرها از Array.from به جای اسپرد ... استفاده کنید، زیرا از ایجاد یک آرایه میانی جلوگیری می کند.
    // ‎بد
    const baz = [...foo].map(bar);

    // ‎خوب
    const baz = Array.from(foo, bar);

  • 4.7 از عبارات بازگشتی در فراخوانی متد آرایه ها استفاده کنید. اگر بدنه تابع از یک عبارت واحد تشکیل شده باشد که یک عبارت را بدون عوارض جانبی برمی گرداند، حذف return اشکالی ندارد. eslint: array-callback-return
    // ‎خوب
    [1, 2, 3].map((x) => {
      const y = x + 1;
      return x * y;
    });

    // ‎خوب
    [1, 2, 3].map((x) => x + 1);

    // ‎بد - بدون مقدار بازگشتی به این معنی است که `acc` پس از اولین تکرار نامشخص می شود
    [[0, 1], [2, 3], [4, 5]].reduce((acc, item, index) => {
      const flatten = acc.concat(item);
    });

    // ‎خوب
    [[0, 1], [2, 3], [4, 5]].reduce((acc, item, index) => {
      const flatten = acc.concat(item);
      return flatten;
    });

    // ‎بد
    inbox.filter((msg) => {
      const { subject, author } = msg;
      if (subject === 'Mockingbird') {
        return author === 'Harper Lee';
      } else {
        return false;
      }
    });

    // ‎خوب
    inbox.filter((msg) => {
      const { subject, author } = msg;
      if (subject === 'Mockingbird') {
        return author === 'Harper Lee';
      }

      return false;
    });

  • 4.8 اگر یک آرایه دارای چندین خط است، پس از باز کردن و قبل از بستن پرانتزهای آرایه، از شکستن خط استفاده کنید.
    // ‎بد
    const arr = [
      [0, 1], [2, 3], [4, 5],
    ];

    const objectInArray = [{
      id: 1,
    }, {
      id: 2,
    }];

    const numberInArray = [
      1, 2,
    ];

    // ‎خوب
    const arr = [[0, 1], [2, 3], [4, 5]];

    const objectInArray = [
      {
        id: 1,
      },
      {
        id: 2,
      },
    ];

    const numberInArray = [
      1,
      2,
    ];

⬆ بازگشت به بالا

استخراج(Destructuring)

  • 5.1 هنگام دسترسی و استفاده از چندین ویژگی یک شی، از استخراج ساختار استفاده کنید. eslint: prefer-destructuring

    چرا؟ Destructuring شما را از ایجاد مراجع موقت برای آن ویژگی ها و دسترسی مکرر به شیء نجات می دهد. تکرار دسترسی به شیء کدهای تکراری بیشتری ایجاد می کند، به خواندن بیشتر نیاز دارد و فرصت های بیشتری برای اشتباهات ایجاد می کند. استخراج اشیاء همچنین به جای نیاز به خواندن کل بلوک برای تعیین آنچه مورد استفاده قرار می گیرد، یک مکان واحد برای تعریف ساختار شیء که در بلوک استفاده می شود، ارائه می دهد.

    // ‎بد
    function getFullName(user) {
      const firstName = user.firstName;
      const lastName = user.lastName;

      return `${firstName} ${lastName}`;
    }

    // ‎خوب
    function getFullName(user) {
      const { firstName, lastName } = user;
      return `${firstName} ${lastName}`;
    }

    // ‎بهترین
    function getFullName({ firstName, lastName }) {
      return `${firstName} ${lastName}`;
    }

    const arr = [1, 2, 3, 4];

    // ‎بد
    const first = arr[0];
    const second = arr[1];

    // ‎خوب
    const [first, second] = arr;

  • 5.3 از ساختارشکنی شیء برای مقادیر چندگانه بازگشتی استفاده کنید، نه برای استخراج آرایه.

    چرا؟ می‌توانید به مرور زمان ویژگی‌های جدید اضافه کنید یا ترتیب کارها را بدون شکستن سایت‌های تماس تغییر دهید.

    // ‎بد
    function processInput(input) {
      // ‎سپس معجزه رخ می دهد
      return [left, right, top, bottom];
    }

    // ‎تماس گیرنده باید در مورد ترتیب برگشت داده ها فکر کند
    const [left, __, top] = processInput(input);

    // ‎خوب
    function processInput(input) {
      // ‎سپس معجزه رخ می دهد
      return { left, right, top, bottom };
    }

    // ‎تماس گیرنده فقط داده های مورد نیاز خود را انتخاب می کند
    const { left, top } = processInput(input);

⬆ بازگشت به بالا

رشته ها

  • 6.1 برای رشته ها از '' از نقل قول های تک استفاده کنید. eslint: quotes
    // ‎بد
    const name = "Capt. Janeway";

    // ‎بد - لیترال ها باید شامل درون یابی یا خطوط جدید باشند
    const name = `Capt. Janeway`;

    // ‎خوب
    const name = 'Capt. Janeway';

  • 6.2 رشته هایی که باعث می شوند خط بیش از 100 کاراکتر باشد، نباید با استفاده از الحاق رشته ها در چندین خط نوشته شوند.

    چرا؟ کار با رشته های شکسته عذاب آور است و باعث می شود که کد کمتر قابل جستجو باشد.

    // ‎بد
    const errorMessage = 'This is a super long error that was thrown because \
    of Batman. When you stop to think about how Batman had anything to do \
    with this, you would get nowhere \
    fast.';

    // ‎بد
    const errorMessage = 'This is a super long error that was thrown because ' +
      'of Batman. When you stop to think about how Batman had anything to do ' +
      'with this, you would get nowhere fast.';

    // ‎خوب
    const errorMessage = 'This is a super long error that was thrown because of Batman. When you stop to think about how Batman had anything to do with this, you would get nowhere fast.';

  • 6.3 هنگام ساختن رشته ها از طریق برنامه، از رشته های الگویی به جای الحاق استفاده کنید. eslint: prefer-template template-curly-spacing

    چرا؟ رشته های الگویی به شما یک سینتکس خوانا و مختصر با خطوط جدید مناسب و ویژگی های درون یابی رشته ای می دهد.

    // ‎بد
    function sayHi(name) {
      return 'How are you, ' + name + '?';
    }

    // ‎بد
    function sayHi(name) {
      return ['How are you, ', name, '?'].join();
    }

    // ‎بد
    function sayHi(name) {
      return `How are you, ${ name }?`;
    }

    // ‎خوب
    function sayHi(name) {
      return `How are you, ${name}?`;
    }

  • 6.4 در یک رشته هرگز از ()eval استفاده نکنید زیرا آسیب پذیری های زیادی را به برنامه اضافه میکند.
    eslint: no-eval

  • 6.5 بی جهت از کاراکتر \ در رشته ها استفاده نکنید. eslint: no-useless-escape

    چرا؟ \ به خوانایی کد آسیب می‌رسانند، بنابراین فقط در صورت لزوم باید وجود داشته باشند.

    // ‎بد
    const foo = '\'this\' \i\s \"quoted\"';

    // ‎خوب
    const foo = '\'this\' is "quoted"';
    const foo = `my name is '${name}'`;

⬆ بازگشت به بالا

توابع

  • 7.1 به جای اعلان تابع از عبارات تابع نامگذاری شده استفاده کنید. eslint: func-style

    چرا؟ اعلان‌های تابع بالا می‌روند، به این معنی که ارجاع به تابع قبل از تعریف در فایل خیلی آسان است. این به خوانایی و قابلیت نگهداری آسیب می رساند. اگر متوجه شدید که تعریف یک تابع به اندازه کافی بزرگ یا پیچیده است که در درک بقیه فایل اختلال ایجاد می کند، شاید وقت آن رسیده که آن را در ماژول خودش استخراج کنید! فراموش نکنید که صراحتاً عبارت را نامگذاری کنید، صرف نظر از اینکه نام از متغیر حاوی استنباط شده باشد یا نه (که اغلب در مرورگرهای مدرن یا هنگام استفاده از کامپایلرهایی مانند Babel چنین است). این هر گونه فرضی را که در مورد پشته تماس خطا وجود دارد حذف می کند. (بحث)

    // ‎بد
    function foo() {
      // ...
    }

    // ‎بد
    const foo = function () {
      // ...
    };

    // ‎خوب
    // ‎نام واژگانی متمایز از فراخوان ارجاع شده به متغیر
    const short = function longUniqueMoreDescriptiveLexicalFoo() {
      // ...
    };

  • 7.2 عبارات تابع فورا فراخوانی شده را در پرانتز قرار دهید. eslint: wrap-iife

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

    // ‎عبارت تابع فوری فراخوانی شده (IIFE)
    (function () {
      console.log('Welcome to the Internet. Please follow me.');
    }());

  • 7.3 هرگز یک تابع را در یک بلوک غیر تابعی (if، while و غیره) اعلام نکنید. به جای آن تابع را به یک متغیر اختصاص دهید. مرورگرها به شما اجازه انجام این کار را می‌دهند، اما همه آن‌ها آن را متفاوت تفسیر می‌کنند، که خبر بدی است. eslint: no-loop-func

  • 7.4 نکته: ECMA-262 یک block را به عنوان لیستی از عبارات تعریف می کند. اعلان تابع یک عبارت نیست.
    // ‎بد
    if (currentUser) {
      function test() {
        console.log('Nope.');
      }
    }

    // ‎خوب
    let test;
    if (currentUser) {
      test = () => {
        console.log('Yup.');
      };
    }

  • 7.5 هرگز پارامتری را arguments نامگذاری نکنید. این موضوع بر شیء arguments که به هر محدوده تابعی داده می شود اولویت خواهد داشت.
    // ‎بد
    function foo(name, options, arguments) {
      // ...
    }

    // ‎خوب
    function foo(name, options, args) {
      // ...
    }

  • 7.6 هرگز از arguments استفاده نکنید، به جای آن از دستور rest ... استفاده کنید. eslint: prefer-rest-params

    چرا؟ ... در مورد اینکه کدام آرگومان‌هایی را می‌خواهید بکشید، صریح است. بعلاوه، آرگومان‌های rest یک آرایه واقعی هستند و فقط آرگومان‌های آرایه مانند نیستند.

    // ‎بد
    function concatenateAll() {
      const args = Array.prototype.slice.call(arguments);
      return args.join('');
    }

    // ‎خوب
    function concatenateAll(...args) {
      return args.join('');
    }

  • 7.7 به جای تغییر (mutate) در آرگومان های تابع، از نحو پارامتر پیش فرض استفاده کنید.
    // ‎بسیار بد
    function handleThings(opts) {
      // ‎نه! ما نباید آرگومان های تابع را تغییر دهیم.
      // ‎مضاعف بد: اگر گزینه‌ها نادرست باشد، روی یک شیء تنظیم می‌شود که ممکن است
      // ‎همان چیزی باشد که شما می‌خواهید اما می‌تواند اشکالات ظریفی را ایجاد کند.
      opts = opts || {};
      // ...
    }

    // ‎همچنان بد
    function handleThings(opts) {
      if (opts === void 0) {
        opts = {};
      }
      // ...
    }

    // ‎خوب
    function handleThings(opts = {}) {
      // ...
    }

  • 7.8 با پارامترهای پیش فرض از عوارض جانبی اجتناب کنید.

    چرا؟ آنها برای استدلال گیج کننده هستند.

    let b = 1;
    // ‎بد
    function count(a = b++) {
      console.log(a);
    }
    count();  // 1
    count();  // 2
    count(3); // 3
    count();  // 3

  • 7.9 همیشه پارامترهای پیش فرض را در آخر قرار دهید. eslint: default-param-last
    // ‎بد
    function handleThings(opts = {}, name) {
      // ...
    }

    // ‎خوب
    function handleThings(name, opts = {}) {
      // ...
    }

  • 7.10 هرگز از سازنده تابع برای ایجاد یک تابع جدید استفاده نکنید. eslint: no-new-func

    چرا؟ ایجاد یک تابع به این روش، رشته ای را مشابه eval() ارزیابی می کند که آسیب پذیری ها را باز می کند.

    // ‎بد
    const add = new Function('a', 'b', 'return a + b');

    // ‎همچنان بد
    const subtract = Function('a', 'b', 'return a - b');

  • 7.11 فاصله گذاری در امضای تابع eslint: space-before-function-paren space-before-blocks

    چرا؟ سازگاری خوب است، و هنگام افزودن یا حذف نام، مجبور نیستید فضایی را اضافه یا حذف کنید.

    // ‎بد
    const f = function(){};
    const g = function (){};
    const h = function() {};

    // ‎خوب
    const x = function () {};
    const y = function a() {};

  • 7.12 هرگز پارامترها را تغییر ندهید. eslint: no-param-reassign

    چرا؟ دستکاری اشیاء ارسال شده به عنوان پارامتر می تواند باعث ایجاد عوارض جانبی متغیر ناخواسته در تماس گیرنده اصلی شود.

    // ‎بد
    function f1(obj) {
      obj.key = 1;
    }

    // ‎خوب
    function f2(obj) {
      const key = Object.prototype.hasOwnProperty.call(obj, 'key') ? obj.key : 1;
    }

  • 7.13 هرگز پارامترها را تغییر ندهید. eslint: no-param-reassign

    را؟ تخصیص مجدد پارامترها می‌تواند منجر به رفتار غیرمنتظره شود، به‌ویژه هنگام دسترسی به شیء arguments. همچنین می تواند باعث مشکلات بهینه سازی شود، به خصوص در موتور جاوا اسکریپت V8.

    // ‎بد
    function f1(a) {
      a = 1;
      // ...
    }

    function f2(a) {
      if (!a) { a = 1; }
      // ...
    }

    // ‎خوب
    function f3(a) {
      const b = a || 1;
      // ...
    }

    function f4(a = 1) {
      // ...
    }

  • 7.14 برای فراخوانی توابع متغیر، استفاده از اسپرد سینتکس ... را ترجیح دهید. eslint: prefer-spread

    چرا؟ اینگونه کد تمیزتر است، شما نیازی به ارائه یک زمینه ندارید، و نمی توانید به راحتی apply با new بنویسید.

    // ‎بد
    const x = [1, 2, 3, 4, 5];
    console.log.apply(console, x);

    // ‎خوب
    const x = [1, 2, 3, 4, 5];
    console.log(...x);

    // ‎بد
    new (Function.prototype.bind.apply(Date, [null, 2016, 8, 5]));

    // ‎خوب
    new Date(...[2016, 8, 5]);

  • 7.15 توابع با امضای چند خطی یا فراخوانی باید درست مانند هر فهرست چند خطی دیگر در این راهنما تورفتگی داشته باشند: با هر مورد در یک خط به تنهایی، با یک کاما انتهایی در آخرین مورد. eslint: function-paren-newline
    // ‎بد
    function foo(bar,
                 baz,
                 quux) {
      // ...
    }

    // ‎خوب
    function foo(
      bar,
      baz,
      quux,
    ) {
      // ...
    }

    // ‎بد
    console.log(foo,
      bar,
      baz);

    // ‎خوب
    console.log(
      foo,
      bar,
      baz,
    );

⬆ بازگشت به بالا

توابع پیکانی

  • 8.1 هنگامی که باید از یک تابع ناشناس استفاده کنید (مانند هنگام ارسال یک تماس درونی)، از نماد تابع فلش استفاده کنید. eslint: prefer-arrow-callback, arrow-spacing

    چرا؟ این یک نسخه از تابع را ایجاد می کند که در زمینه this اجرا می شود، که معمولاً همان چیزی است که شما می خواهید، و یک سینتکس مختصرتر است.

    چرا که نه؟ اگر یک تابع نسبتاً پیچیده دارید، ممکن است آن منطق را به عبارت تابع نام‌گذاری شده خودش منتقل کنید.

    // ‎بد
    [1, 2, 3].map(function (x) {
      const y = x + 1;
      return x * y;
    });

    // ‎خوب
    [1, 2, 3].map((x) => {
      const y = x + 1;
      return x * y;
    });

  • 8.2 اگر بدنه تابع از یک عبارت واحد تشکیل شده است که یک عبارت را بدون عوارض جانبی برمی گرداند، بریس ها را حذف کنید و استفاده کنید. بازگشت ضمنی در غیر این صورت، بریس ها را نگه دارید و از عبارت return استفاده کنید. eslint: arrow-parens, arrow-body-style

    چرا؟ خوانایی بهتر. هنگامی که چندین تابع به هم متصل می شوند،کد به خوبی خوانده می شود.

    // ‎بد
    [1, 2, 3].map((number) => {
      const nextNumber = number + 1;
      `A string containing the ${nextNumber}.`;
    });

    // ‎خوب
    [1, 2, 3].map((number) => `A string containing the ${number + 1}.`);

    // ‎خوب
    [1, 2, 3].map((number) => {
      const nextNumber = number + 1;
      return `A string containing the ${nextNumber}.`;
    });

    // ‎خوب
    [1, 2, 3].map((number, index) => ({
      [index]: number,
    }));

    // ‎بدون بازگشت ضمنی با عوارض جانبی
    function foo(callback) {
      const val = callback();
      if (val === true) {
        // ‎اگر تماس برگشتی true است، کاری انجام دهید
      }
    }

    let bool = false;

    // ‎بد
    foo(() => bool = true);

    // ‎خوب
    foo(() => {
      bool = true;
    });

  • 8.3 در صورتی که عبارت در چندین خط باشد، برای خوانایی بهتر، آن را در پرانتز قرار دهید.

    چرا؟ این به وضوح نشان می دهد که تابع کجا شروع شده و به پایان می رسد.

    // ‎بد
    ['get', 'post', 'put'].map((httpMethod) => Object.prototype.hasOwnProperty.call(
        httpMagicObjectWithAVeryLongName,
        httpMethod,
      )
    );

    // ‎خوب
    ['get', 'post', 'put'].map((httpMethod) => (
      Object.prototype.hasOwnProperty.call(
        httpMagicObjectWithAVeryLongName,
        httpMethod,
      )
    ));

  • 8.4 برای وضوح و سازگاری همیشه پرانتزها را در اطراف استدلال ها قرار دهید. eslint: arrow-parens

    چرا؟ هنگام افزودن یا حذف آرگومان‌ها، تغییر تفاوت را به حداقل می‌رساند.

    // ‎بد
    [1, 2, 3].map(x => x * x);

    // ‎خوب
    [1, 2, 3].map((x) => x * x);

    // ‎بد
    [1, 2, 3].map(number => (
      `A long string with the ${number}. It’s so long that we don’t want it to take up space on the .map line!`
    ));

    // ‎خوب
    [1, 2, 3].map((number) => (
      `A long string with the ${number}. It’s so long that we don’t want it to take up space on the .map line!`
    ));

    // ‎بد
    [1, 2, 3].map(x => {
      const y = x + 1;
      return x * y;
    });

    // ‎خوب
    [1, 2, 3].map((x) => {
      const y = x + 1;
      return x * y;
    });

  • 8.5 از گیج شدن نحو تابع پیکان (=>) با عملگرهای مقایسه (<=، >=) خودداری کنید. eslint: no-confusing-arrow
    // ‎بد
    const itemHeight = (item) => item.height <= 256 ? item.largeSize : item.smallSize;

    // ‎بد
    const itemHeight = (item) => item.height >= 256 ? item.largeSize : item.smallSize;

    // ‎خوب
    const itemHeight = (item) => (item.height <= 256 ? item.largeSize : item.smallSize);

    // ‎خوب
    const itemHeight = (item) => {
      const { height, largeSize, smallSize } = item;
      return height <= 256 ? largeSize : smallSize;
    };

  • 8.6 مکان بدنه های تابع پیکان را با بازگشت های ضمنی اعمال کنید. eslint: implicit-arrow-linebreak
    // ‎بد
    (foo) =>
      bar;

    (foo) =>
      (bar);

    // ‎خوب
    (foo) => bar;
    (foo) => (bar);
    (foo) => (
       bar
    )

⬆ بازگشت به بالا

کلاس ها و سازندگان

  • 9.1 همیشه از class استفاده کنید. از دستکاری مستقیم prototype خودداری کنید.

    چرا؟ سینتکس class مختصرتر و ساده‌تر است.

    // ‎بد
    function Queue(contents = []) {
      this.queue = [...contents];
    }
    Queue.prototype.pop = function () {
      const value = this.queue[0];
      this.queue.splice(0, 1);
      return value;
    };

    // ‎خوب
    class Queue {
      constructor(contents = []) {
        this.queue = [...contents];
      }
      pop() {
        const value = this.queue[0];
        this.queue.splice(0, 1);
        return value;
      }
    }

  • 9.2 برای ارث بردن از extends استفاده کنید.

    چرا؟ این یک روش داخلی برای به ارث بردن عملکرد نمونه اولیه بدون شکستن instanceof است.

    // ‎بد
    const inherits = require('inherits');
    function PeekableQueue(contents) {
      Queue.apply(this, contents);
    }
    inherits(PeekableQueue, Queue);
    PeekableQueue.prototype.peek = function () {
      return this.queue[0];
    };

    // ‎خوب
    class PeekableQueue extends Queue {
      peek() {
        return this.queue[0];
      }
    }

  • 9.3 متد‌ها می‌توانند this را برای کمک به زنجیره‌سازی متد برگردانند.
    // ‎بد
    Jedi.prototype.jump = function () {
      this.jumping = true;
      return true;
    };

    Jedi.prototype.setHeight = function (height) {
      this.height = height;
    };

    const luke = new Jedi();
    luke.jump(); // => true
    luke.setHeight(20); // => undefined

    // ‎خوب
    class Jedi {
      jump() {
        this.jumping = true;
        return this;
      }

      setHeight(height) {
        this.height = height;
        return this;
      }
    }

    const luke = new Jedi();

    luke.jump()
      .setHeight(20);

  • 9.4 نوشتن یک متد سفارشی ()toString اشکالی ندارد، فقط مطمئن شوید که با موفقیت کار می کند و عوارض جانبی ایجاد نمی کند.
    class Jedi {
      constructor(options = {}) {
        this.name = options.name || 'no name';
      }

      getName() {
        return this.name;
      }

      toString() {
        return `Jedi - ${this.getName()}`;
      }
    }

  • 9.5 در صورتی که کلاس ها یک سازنده پیش فرض داشته باشند. یک تابع سازنده خالی یا تابعی که فقط به یک کلاس والد واگذار می شود، ضروری نیست. eslint: no-useless-constructor
    // ‎بد
    class Jedi {
      constructor() {}

      getName() {
        return this.name;
      }
    }

    // ‎بد
    class Rey extends Jedi {
      constructor(...args) {
        super(...args);
      }
    }

    // ‎خوب
    class Rey extends Jedi {
      constructor(...args) {
        super(...args);
        this.name = 'Rey';
      }
    }

  • 9.6 از تکرار اعضای کلاس خودداری کنید. eslint: no-dupe-class-members

    چرا؟ اعلان‌های تکراری اعضای کلاس بی‌صدا آخرین مورد را ترجیح می‌دهند - تقریباً و مطمئناً داشتن موارد تکراری یک اشکال و باگ است.

    // ‎بد
    class Foo {
      bar() { return 1; }
      bar() { return 2; }
    }

    // ‎خوب
    class Foo {
      bar() { return 1; }
    }

    // ‎خوب
    class Foo {
      bar() { return 2; }
    }

  • 9.7 متدهای کلاس باید از this استفاده کنند یا به یک روش ثابت تبدیل شوند، مگر اینکه یک کتابخانه یا چارچوب خارجی نیاز به استفاده از روش‌های غیراستاتیک خاصی داشته باشد. یک روش نمونه بودن باید نشان دهد که بر اساس ویژگی های گیرنده رفتار متفاوتی دارد.
    eslint: class-methods-use-this
    // ‎بد
    class Foo {
      bar() {
        console.log('bar');
      }
    }

    // ‎خوب - این استفاده می شود
    class Foo {
      bar() {
        console.log(this.bar);
      }
    }

    // ‎خوب - سازنده معاف است
    class Foo {
      constructor() {
        // ...
      }
    }

    // ‎خوب - انتظار نمی رود روش های استاتیک از این استفاده کنند
    class Foo {
      static bar() {
        console.log('bar');
      }
    }

⬆ بازگشت به بالا

ماژول ها

  • 10.1 همیشه از ماژول ها (import/export) روی یک سیستم ماژول غیر استاندارد استفاده کنید. شما همیشه می توانید به سیستم ماژول دلخواه خود انتقال دهید.

    چرا؟ ماژول ها آینده هستند، از همین حالا از آینده استفاده کنید.

    // ‎بد
    const AirbnbStyleGuide = require('./AirbnbStyleGuide');
    module.exports = AirbnbStyleGuide.es6;

    // ‎بد
    import AirbnbStyleGuide from './AirbnbStyleGuide';
    export default AirbnbStyleGuide.es6;

    // ‎بهترین
    import { es6 } from './AirbnbStyleGuide';
    export default es6;

  • 10.2 از واردات عام استفاده نکنید.

    چرا؟ این اطمینان حاصل می کند که یک export default دارید.

    // ‎بد
    import * as AirbnbStyleGuide from './AirbnbStyleGuide';

    // ‎خوب
    import AirbnbStyleGuide from './AirbnbStyleGuide';

  • 10.3 و مستقیماً از واردات، صادر نکنید.

    چرا؟ اگرچه خط یک خط مختصر است، اما داشتن یک راه واضح برای واردات و یک راه مشخص برای صادرات، همه چیز را منسجمتر می کند.

    // ‎بد
    // ‎نام فایل es6.js
    export { es6 as default } from './AirbnbStyleGuide';

    // ‎خوب
    // ‎نام فایل es6.js
    import { es6 } from './AirbnbStyleGuide';
    export default es6;

  • 10.4 فقط از یک مسیر در یک مکان وارد کنید. eslint: no-duplicate-imports

    چرا؟ داشتن چندین خط که از یک مسیر وارد می شوند، می تواند حفظ کد را سخت تر کند.

    // ‎بد
    import foo from 'foo';
    // ‎… برخی دیگر از واردات … //
    import { named1, named2 } from 'foo';

    // ‎خوب
    import foo, { named1, named2 } from 'foo';

    // ‎خوب
    import foo, {
      named1,
      named2,
    } from 'foo';

  • 10.5 پیوندهای قابل تغییر صادر نکنید. eslint: import/no-mutable-exports

    چرا؟ باید از mutation به طور کلی اجتناب شود، اما به طور خاص هنگام صادرات اتصالات قابل تغییر، در حالی که ممکن است این تکنیک برای برخی موارد خاص مورد نیاز باشد، به طور کلی، فقط مراجع ثابت باید صادر شوند.

    // ‎بد
    let foo = 3;
    export { foo };

    // ‎خوب
    const foo = 3;
    export { foo };

  • 10.6 در ماژول‌هایی با یک صادرات، صادرات پیش‌فرض را به صادرات نام‌گذاری شده ترجیح دهید. eslint: import/prefer-default-export

    چرا؟ برای تشویق فایل های بیشتری که فقط یک چیز را صادر می کنند، که برای خوانایی و نگهداری بهتر است.

    // ‎بد
    export function foo() {}

    // ‎خوب
    export default function foo() {}

  • 10.7 همه import ها را بالای عبارات غیروارداتی قرار دهید. eslint: import/first

    چرا؟ از آنجایی که import ها بالا میروند، نگه داشتن همه آنها در بالا از رفتار غیر منتظرانه کد جلوگیری می‌کند.

    // ‎بد
    import foo from 'foo';
    foo.init();

    import bar from 'bar';

    // ‎خوب
    import foo from 'foo';
    import bar from 'bar';

    foo.init();

  • 10.8 واردات چند خطی باید درست مانند آرایه های چند خطی و متغییر شیء ها دارای تورفتگی باشد. eslint: object-curly-newline

    چرا؟ کرلی بریس ها ( { ) از همان قوانین تورفتگی مانند هر بلوک کرلی بریس های دیگر در راهنمای سبک پیروی می‌کنند، مانند کاماهای انتهایی.

    // ‎بد
    import {longNameA, longNameB, longNameC, longNameD, longNameE} from 'path';

    // ‎خوب
    import {
      longNameA,
      longNameB,
      longNameC,
      longNameD,
      longNameE,
    } from 'path';

  • 10.9 دستور لودر Webpack را در دستورات وارد کردن ماژول مجاز نکنید. eslint: import/no-webpack-loader-syntax

    چرا؟ از آنجایی که استفاده از سینتکس Webpack در واردات، کد را به یک بسته‌کننده ماژول جفت می‌کند. ترجیحاً از سینتکس لودر در webpack.config.js استفاده کنید.

    // ‎بد
    import fooSass from 'css!sass!foo.scss';
    import barCss from 'style!css!bar.css';

    // ‎خوب
    import fooSass from 'foo.scss';
    import barCss from 'bar.css';

  • 10.10 پسوندهای نام فایل جاوا اسکریپت را درج نکنید eslint: import/extensions

    چرا؟ گنجاندن پسوندها از بازآفرینی کد جلوگیری می‌کند و به‌طور نامناسب جزئیات پیاده‌سازی ماژولی را که وارد می‌کنید در هر مصرف‌کننده‌ای را کدگذاری می‌کند.

    // ‎بد
    import foo from './foo.js';
    import bar from './bar.jsx';
    import baz from './baz/index.jsx';

    // ‎خوب
    import foo from './foo';
    import bar from './bar';
    import baz from './baz';

⬆ بازگشت به بالا

تکرار کننده ها و مولدها

  • 11.1 از تکرار کننده ها استفاده نکنید توابع مرتبه بالاتر جاوا اسکریپت را به جای حلقه هایی مانند for-in یا for-of ترجیح دهید.
    eslint: no-iterator no-restricted-syntax

    چرا؟ این قانون تغییر ناپذیری ما را اجرا می کند. پرداختن به توابع خالصی که مقادیر را برمی گرداند آسان تر از داشتن عوارض جانبی است.

    از()map() / every() / filter() / find() / findIndex() / reduce() / some / ... برای تکرار روی آرایه ها استفاده کنید و از ()Object.keys() / Object.values() / Object.entries برای تولید آرایه‌ها تا بتوانید روی اشیادستوراتتان را تکرار کنید.

    const numbers = [1, 2, 3, 4, 5];

    // ‎بد
    let sum = 0;
    for (let num of numbers) {
      sum += num;
    }
    sum === 15;

    // ‎خوب
    let sum = 0;
    numbers.forEach((num) => {
      sum += num;
    });
    sum === 15;

    // ‎بهترین (use the functional force)
    const sum = numbers.reduce((total, num) => total + num, 0);
    sum === 15;

    // ‎بد
    const increasedByOne = [];
    for (let i = 0; i <br numbers.length; i++) {
      increasedByOne.push(numbers[i] + 1);
    }

    // ‎خوب
    const increasedByOne = [];
    numbers.forEach((num) => {
      increasedByOne.push(num + 1);
    });

    // ‎بهترین (عملکردی نگه داشتن آن)
    const increasedByOne = numbers.map((num) => num + 1);

  • 11.2 فعلا از ژنراتور استفاده نکنید.

    چرا؟ آنها به خوبی به ES5 منتقل نمی شوند.

  • 11.3 اگر باید از ژنراتورها استفاده کنید، یا اگر توصیه مارا نادیده می‌گیرید، مطمئن شوید که امضای عملکرد آن‌ها به درستی فاصله دارد. eslint: generator-star-spacing

    چرا؟ function و * بخشی از یک کلمه کلیدی مفهومی هستند - "*" یک اصلاح کننده برای function نیست، function* یک ساختار منحصر به فرد است، متفاوت از function.

    // ‎بد
    function * foo() {
      // ...
    }

    // ‎بد
    const bar = function * () {
      // ...
    };

    // ‎بد
    const baz = function *() {
      // ...
    };

    // ‎بد
    const quux = function*() {
      // ...
    };

    // ‎بد
    function*foo() {
      // ...
    }

    // ‎بد
    function *foo() {
      // ...
    }

    // ‎خیلی بد
    function
    *
    foo() {
      // ...
    }

    // ‎خیلی بد
    const wat = function
    *
    () {
      // ...
    };

    // ‎خوب
    function* foo() {
      // ...
    }

    // ‎خوب
    const foo = function* () {
      // ...
    };

⬆ بازگشت به بالا

خصوصیات

  • 12.1 هنگام دسترسی به ویژگی ها از نماد نقطه استفاده کنید. eslint: dot-notation
    const luke = {
      jedi: true,
      age: 28,
    };

    // ‎بد
    const isJedi = luke['jedi'];

    // ‎خوب
    const isJedi = luke.jedi;

  • 12.2 هنگام دسترسی به خصوصیات با یک متغیر، از علامت براکت [] استفاده کنید.
    const luke = {
      jedi: true,
      age: 28,
    };

    function getProp(prop) {
      return luke[prop];
    }

    const isJedi = getProp('jedi');

    // ‎بد
    const binary = Math.pow(2, 10);

    // ‎خوب
    const binary = 2 ** 10;

⬆ بازگشت به بالا

متغیرها

  • 13.1 همیشه از const یا let برای اعلام متغیرها استفاده کنید. عدم انجام این کار باعث ایجاد متغیرهای سراسری می شود. ما می خواهیم از آلودگی فضای نام جهانی جلوگیری کنیم.جلوتر به شما در این مورد هشدار داده ایم.
    eslint: no-undef prefer-const
    // ‎بد
    superPower = new SuperPower();

    // ‎خوب
    const superPower = new SuperPower();

  • 13.2 برای هر متغیر یا تخصیص از یک اعلان const یا let استفاده کنید. eslint: one-var

    چرا؟ اضافه کردن اعلان‌های متغیر جدید از این طریق آسان‌تر است، و هرگز لازم نیست نگران تعویض یک ; با , یا معرفی تفاوت‌های فقط نشانه‌گذاری باشید. همچنین می‌توانید به‌جای اینکه به‌طور هم‌زمان از همه آن‌ها عبور کنید، با دیباگر از هر اعلان عبور کنید.

    // ‎بد
    const items = getItems(),
        goSportsTeam = true,
        dragonball = 'z';

    // ‎بد
    // ‎(با بالا مقایسه کنید و سعی کنید اشتباه را تشخیص دهید)
    const items = getItems(),
        goSportsTeam = true;
        dragonball = 'z';

    // ‎خوب
    const items = getItems();
    const goSportsTeam = true;
    const dragonball = 'z';

  • 13.3 همه const های خود را گروه بندی کنید و سپس همه let های خود را گروه بندی کنید.

    چرا؟ این زمانی مفید است که بعداً ممکن است لازم باشد متغیری را بسته به یکی از متغیرهای قبلاً اختصاص داده شده تغییر دهید.

    // ‎بد
    let i, len, dragonball,
        items = getItems(),
        goSportsTeam = true;

    // ‎بد
    let i;
    const items = getItems();
    let dragonball;
    const goSportsTeam = true;
    let len;

    // ‎خوب
    const goSportsTeam = true;
    const items = getItems();
    let dragonball;
    let i;
    let length;

  • 13.4 متغیرها را در جایی که به آنها نیاز دارید اختصاص دهید، اما آنها را در مکانی معقول قرار دهید.

    چرا؟ let و const دارای محدوده بلوکی هستند و محدوده عملکردی ندارند.

    // ‎بد - فراخوانی غیر ضروری عملکرد 
    function checkName(hasName) {
      const name = getName();

      if (hasName === 'test') {
        return false;
      }

      if (name === 'test') {
        this.setName('');
        return false;
      }

      return name;
    }

    // ‎خوب
    function checkName(hasName) {
      if (hasName === 'test') {
        return false;
      }

      const name = getName();

      if (name === 'test') {
        this.setName('');
        return false;
      }

      return name;
    }

  • 13.5 تعاریف متغیر ها را زنجیره ای نکنید. eslint: no-multi-assign

    چرا؟ تخصیص متغیرهای زنجیره ای، متغیرهای جهانی ضمنی ایجاد می کند.

    // ‎بد
    (function example() {
      // ‎جاوا اسکریپت این را چنین تفسیر می کند
      // let a = ( b = ( c = 1 ) );
      // ‎کلمه کلیدی let فقط برای متغیر a کاربرد دارد. متغیرهای b و c تبدیل می شوند
      // ‎متغیرهای جهانی.
      let a = b = c = 1;
    }());

    console.log(a); // ‎خطای ReferenceError
    console.log(b); // 1
    console.log(c); // 1

    // ‎خوب
    (function example() {
      let a = 1;
      let b = a;
      let c = a;
    }());

    console.log(a); // ‎خطای ReferenceError
    console.log(b); // ‎خطای ReferenceError
    console.log(c); // ‎خطای ReferenceError

    // ‎همین امر برای 'const' نیز صدق می کند

  • 13.6 از استفاده از افزایش و کاهش یکنواخت خودداری کنید (++، --). eslint no-plusplus

    چرا؟ طبق مستندات Eslint، گزاره‌های افزایش و کاهش یکنواخت مشمول درج خودکار نقطه ویرگول هستند و می‌توانند باعث خطاهای بی‌صدا با مقادیر افزایش یا کاهش در یک برنامه شوند. همچنین جهش دادن مقادیر خود با عباراتی مانند num += 1 به جای num++ یا num ++ گویاتر است. عدم اجازه دادن به گزاره‌های افزایش و کاهش یکنواخت همچنین مانع از افزایش/پیش کاهش مقادیر غیرعمدی می‌شود که می‌تواند باعث رفتار غیرمنتظره در برنامه‌های شما شود.

    // ‎بد

    const array = [1, 2, 3];
    let num = 1;
    num++;
    --num;

    let sum = 0;
    let truthyCount = 0;
    for (let i = 0; i < array.length; i++) {
      let value = array[i];
      sum += value;
      if (value) {
        truthyCount++;
      }
    }

    // ‎خوب

    const array = [1, 2, 3];
    let num = 1;
    num += 1;
    num -= 1;

    const sum = array.reduce((a, b) => a + b, 0);
    const truthyCount = array.filter(Boolean).length;

  • 13.7 از شکستن خط قبل یا بعد از = در تعریف یک متغیر اجتناب کنید. If your assignment violates max-len, مقدار را در پرانتز احاطه کنید. eslint operator-linebreak.

    چرا؟ شکستن خط ها اطراف = می تواند مقدار یک انتساب را مبهم کند.

    // ‎بد
    const foo =
      superLongLongLongLongLongLongLongLongFunctionName();

    // ‎بد
    const foo
      = 'superLongLongLongLongLongLongLongLongString';

    // ‎خوب
    const foo = (
      superLongLongLongLongLongLongLongLongFunctionName()
    );

    // ‎خوب
    const foo = 'superLongLongLongLongLongLongLongLongString';

  • 13.8 متغیرهای استفاده نشده را مجاز نکنید. eslint: no-unused-vars

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

    // ‎بد

    const some_unused_var = 42;

    // ‎متغیرهای فقط نوشتن به عنوان استفاده شده در نظر گرفته نمی شوند.
    let y = 10;
    y = 5;

    // ‎خواندن برای اصلاح خود به عنوان مورد استفاده در نظر گرفته نمی شود.
    let z = 0;
    z = z + 1;

    // ‎آرگومان های تابع استفاده نشده
    function getX(x, y) {
        return x;
    }

    // ‎خوب

    function getXPlusY(x, y) {
      return x + y;
    }

    const x = 1;
    const y = a + 2;

    alert(getXPlusY(x, y));

    // ‎'type' نادیده گرفته می شود، حتی اگر استفاده نشده باشد، زیرا دارای یک خواهر و برادر دارایی استراحت است.
    // ‎این شکلی از استخراج یک شیء است که کلیدهای مشخص شده را حذف می کند.
    const { type, ...coords } = data;
    // ‎'coords' اکنون شیء 'data' بدون خاصیت 'type' آن است.

⬆ بازگشت به بالا

بالا بردن

  • 14.1 اعلان‌های var به بالای نزدیک‌ترین محدوده تابع محصورکننده خود بالا می‌روند، اما تخصیص آنها اینطور نیست. اعلان‌های const و let با مفهوم جدیدی به نام Temporal Dead Zones (TDZ) همراه هستند، مهم است بدانیم چرا typeof ایمن نیست.
    // ‎ما می دانیم که این کار نمی کند (با فرض وجود
    // ‎متغیر جهانی notDefined تعریف نشده است)
    function example() {
      console.log(notDefined); // => ‎خطای ReferenceError
    }

    // ‎ایجاد یک اعلان متغیر پس از ارجاع به متغیر به دلیل بالا بردن متغیر کار خواهد کرد.
    // ‎توجه: مقدار تخصیص `true` بالا نمی رود.
    function example() {
      console.log(declaredButNotAssigned); // => undefined
      var declaredButNotAssigned = true;
    }

    // ‎مفسر در حال بالا بردن اعلان متغیر در بالای دامنه است،
    // ‎به این معنی که مثال ما می تواند به صورت زیر بازنویسی شود:
    function example() {
      let declaredButNotAssigned;
      console.log(declaredButNotAssigned); // => undefined
      declaredButNotAssigned = true;
    }

    // ‎استفاده از const و let
    function example() {
      console.log(declaredButNotAssigned); // => خطای ReferenceError
      console.log(typeof declaredButNotAssigned); // => خطای ReferenceError
      const declaredButNotAssigned = true;
    }

  • 14.2 عبارات تابع ناشناس نام متغیر خود را بالا می برند، اما تخصیص تابع نه.
    function example() {
      console.log(anonymous); // => undefined

      anonymous(); // => TypeError anonymous یک تابع نیست

      var anonymous = function () {
        console.log('anonymous function expression');
      };
    }

  • 14.3 عبارات تابع نامگذاری شده نام متغیر را بالا می برند، نه نام تابع یا بدنه تابع.
    function example() {
      console.log(named); // => undefined

      named(); // => TypeError named یک تابع نیست

      superPower(); // => ReferenceError superPower تعریف نشده است

      var named = function superPower() {
        console.log('Flying');
      };
    }

    // ‎زمانی که نام تابع با نام متغیر یکسان باشد، همین امر صادق است.
    function example() {
      console.log(named); // => undefined

      named(); // => TypeError named یک تابع نیست

      var named = function named() {
        console.log('named');
      };
    }

  • 14.4 اعلان های تابع نام و بدنه عملکرد را بالا می برند.
    function example() {
      superPower(); // => Flying

      function superPower() {
        console.log('Flying');
      }
    }

⬆ بازگشت به بالا

اپراتورهای مقایسه و برابری

  • 15.1 از === و !== مقابل == و != استفاده کنید. eslint: eqeqeq

  • 15.2 عبارات شرطی مانند عبارت if بیان خود را با استفاده از اجبار با روش انتزاعی ToBoolean ارزیابی می کنند و همیشه از این قوانین ساده پیروی می کنند.:

  • Objects میشود true

  • Undefined میشود false

  • Null میشود false

  • Booleans میشود مقدار boolean

  • Numbers میشود false اگر +0, -0, or NaN, در غیر این صورت true

  • Strings میشود false اگر یک رشته خالی '', در غیر این صورت true

    if ([0] && []) {
      // true
      // ‎یک آرایه (حتی یک آرایه خالی) یک شیء است، اشیاء به درستی ارزیابی می شوند
    }

  • 15.3 از میانبرها برای Boolean ها استفاده کنید، اما از مقایسه صریح برای رشته ها و اعداد استفاده کنید.
    // ‎بد
    if (isValid === true) {
      // ...
    }

    // ‎خوب
    if (isValid) {
      // ...
    }

    // ‎بد
    if (name) {
      // ...
    }

    // ‎خوب
    if (name !== '') {
      // ...
    }

    // ‎بد
    if (collection.length) {
      // ...
    }

    // ‎خوب
    if (collection.length > 0) {
      // ...
    }

  • 15.5 ز پرانتزها برای ایجاد بلوک‌هایی در عبارت‌های case و default استفاده کنید که حاوی اعلان‌های لغوی هستند (مثلاً let، const، function و class). eslint: no-case-declarations

    چرا؟ سینتکس های واژگانی در کل بلوک سوئیچ قابل مشاهده هستند، اما فقط زمانی که تخصیص داده می‌شوند، مقداردهی اولیه می‌شوند، که تنها زمانی اتفاق می‌افتد که به حرف آن برسد. زمانی که چندین بند مورد سعی می‌کنند یک چیز را تعریف کنند، این مشکل ایجاد می‌کند.

    // ‎بد
    switch (foo) {
      case 1:
        let x = 1;
        break;
      case 2:
        const y = 2;
        break;
      case 3:
        function f() {
          // ...
        }
        break;
      default:
        class C {}
    }

    // ‎خوب
    switch (foo) {
      case 1: {
        let x = 1;
        break;
      }
      case 2: {
        const y = 2;
        break;
      }
      case 3: {
        function f() {
          // ...
        }
        break;
      }
      case 4:
        bar();
        break;
      default: {
        class C {}
      }
    }

  • 15.6 ترنری ها نباید تودرتو باشند و عموماً باید عبارت های تک خطی باشند. eslint: no-nested-ternary
    // ‎بد
    const foo = maybe1 > maybe2
      ? "bar"
      : value1 > value2 ? "baz" : null;

    // ‎به 2 عبارت سه تایی جدا شده تقسیم می شود
    const maybeNull = value1 > value2 ? 'baz' : null;

    // ‎بهتر
    const foo = maybe1 > maybe2
      ? 'bar'
      : maybeNull;

    // ‎بهترین
    const foo = maybe1 > maybe2 ? 'bar' : maybeNull;

    // ‎بد
    const foo = a ? a : b;
    const bar = c ? true : false;
    const baz = c ? false : true;
    const quux = a != null ? a : b;

    // ‎خوب
    const foo = a || b;
    const bar = !!c;
    const baz = !c;
    const quux = a ?? b;

  • 15.8 هنگام مخلوط کردن عملگرها، آنها را داخل پرانتز قرار دهید. تنها استثنا عملگرهای حسابی استاندارد هستند: +، -، و ** زیرا تقدم آنها به طور گسترده درک شده است. توصیه می‌کنیم / و * را در پرانتز قرار دهید زیرا اولویت آنها ممکن است زمانی که با هم مخلوط می‌شوند مبهم باشد. eslint: no-mixed-operators

    چرا؟ این خوانایی را بهبود می بخشد و قصد توسعه دهنده را روشن می کند.

    // ‎بد
    const foo = a && b < 0 || c > 0 || d + 1 === 0;

    // ‎بد
    const bar = a ** b - 5 % d;

    // ‎بد
    // ‎ممکن است فرد در فکر کردن گیج شود (a || b) && c
    if (a || b && c) {
      return d;
    }

    // ‎بد
    const bar = a + b / c * d;

    // ‎خوب
    const foo = (a && b <br 0) || c > 0 || (d + 1 === 0);

    // ‎خوب
    const bar = a ** b - (5 % d);

    // ‎خوب
    if (a || (b && c)) {
      return d;
    }

    // ‎خوب
    const bar = a + (b / c) * d;

⬆ بازگشت به بالا

بلوک ها

    // ‎بد
    if (test)
      return false;

    // ‎خوب
    if (test) return false;

    // ‎خوب
    if (test) {
      return false;
    }

    // ‎بد
    function foo() { return false; }

    // ‎خوب
    function bar() {
      return false;
    }

  • 16.2 اگر از بلوک‌های چند خطی با if و else استفاده می‌کنید، else را در همان خط مهاربند بسته شدن بلوک if خود قرار دهید. eslint: brace-style
    // ‎بد
    if (test) {
      thing1();
      thing2();
    }
    else {
      thing3();
    }

    // ‎خوب
    if (test) {
      thing1();
      thing2();
    } else {
      thing3();
    }

  • 16.3 اگر یک بلوک if همیشه عبارت return را اجرا می‌کند، بلوک else بعدی ضروری نیست. یک بازگشت در بلوک اگر دیگر به دنبال بلوک اگر که حاوی بازگشت است، می‌تواند به بلوک‌های اگر متعدد جدا شود. eslint: no-else-return
    // ‎بد
    function foo() {
      if (x) {
        return x;
      } else {
        return y;
      }
    }

    // ‎بد
    function cats() {
      if (x) {
        return x;
      } else if (y) {
        return y;
      }
    }

    // ‎بد
    function dogs() {
      if (x) {
        return x;
      } else {
        if (y) {
          return y;
        }
      }
    }

    // ‎خوب
    function foo() {
      if (x) {
        return x;
      }

      return y;
    }

    // ‎خوب
    function cats() {
      if (x) {
        return x;
      }

      if (y) {
        return y;
      }
    }

    // ‎خوب
    function dogs(x) {
      if (x) {
        if (z) {
          return y;
        }
      } else {
        return z;
      }
    }

⬆ بازگشت به بالا

بیانیه های کنترلی

  • 17.1 در صورتی که دستور کنترل شما (if, while و غیره) بیش از حد طولانی شود یا از حداکثر طول خط فراتر رود، هر شرط (گروه‌بندی شده) را می‌توان در یک خط جدید قرار داد. عملگر منطقی باید خط را شروع کند.

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

    // ‎بد
    if ((foo === 123 || bar === 'abc') && doesItLookGoodWhenItBecomesThatLong() && isThisReallyHappening()) {
      thing1();
    }

    // ‎بد
    if (foo === 123 &&
      bar === 'abc') {
      thing1();
    }

    // ‎بد
    if (foo === 123
      && bar === 'abc') {
      thing1();
    }

    // ‎بد
    if (
      foo === 123 &&
      bar === 'abc'
    ) {
      thing1();
    }

    // ‎خوب
    if (
      foo === 123
      && bar === 'abc'
    ) {
      thing1();
    }

    // ‎خوب
    if (
      (foo === 123 || bar === 'abc')
      && doesItLookGoodWhenItBecomesThatLong()
      && isThisReallyHappening()
    ) {
      thing1();
    }

    // ‎خوب
    if (foo === 123 && bar === 'abc') {
      thing1();
    }

  • 17.2 از عملگرهای انتخاب به جای دستورات کنترلی استفاده نکنید.
    // ‎بد
    !isRunning && startRunning();

    // ‎خوب
    if (!isRunning) {
      startRunning();
    }

⬆ بازگشت به بالا

توضیح نویسی

  • 18.1 برای نظرات چند خطی از /** ... */ استفاده کنید.
    // ‎بد
    // ‎make() یک عنصر جدید را بر اساس نام تگ ارسال شده برمی گرداند
    //
    // @param {String} tag
    // @return {Element} element
    function make(tag) {

      // ...

      return element;
    }

    // ‎خوب
    /**‎
     * ‎make() یک عنصر جدید را بر اساس نام تگ ارسال شده برمی گرداند
     ‎*/
    function make(tag) {

      // ...

      return element;
    }

  • 18.2 برای نظرات تک خطی از // استفاده کنید. نظرات تک خطی را در خط جدید بالای موضوع نظر قرار دهید. یک خط خالی قبل از نظر قرار دهید مگر اینکه در اولین خط یک بلوک باشد.
    // ‎بد
    const active = true;  // ‎برگه فعلی است

    // ‎خوب
    // ‎برگه فعلی است
    const active = true;

    // ‎بد
    function getType() {
      console.log('fetching type...');
      // ‎نوع پیش فرض روی 'no type'
      const type = this.type || 'no type';

      return type;
    }

    // ‎خوب
    function getType() {
      console.log('fetching type...');

      // ‎نوع پیش فرض روی 'no type'
      const type = this.type || 'no type';

      return type;
    }

    // ‎هچنان خوب
    function getType() {
      // ‎نوع پیش فرض روی 'no type'
      const type = this.type || 'no type';

      return type;
    }

  • 18.3 همه نظرات را با یک فاصله شروع کنید تا خواندن آن آسان تر شود. eslint: spaced-comment
    // ‎بد
    //is current tab
    const active = true;

    // ‎خوب
    // is current tab
    const active = true;

    // ‎بد
    /**‎
     * ‎make() یک عنصر جدید را بر اساس نام تگ ارسال شده برمی گرداند
     ‎*/
    function make(tag) {

      // ...

      return element;
    }

    // ‎خوب
    /**‎
     * ‎make() یک عنصر جدید را بر اساس نام تگ ارسال شده برمی گرداند
     ‎*/
    function make(tag) {

      // ...

      return element;
    }

  • 18.4 قرار دادن پیشوند نظرات خود با FIXME یا TODO به سایر برنامه‌نویسان کمک می‌کند تا به سرعت متوجه شوند که آیا به مشکلی اشاره می‌کنید که باید دوباره بررسی شود یا راه‌حلی برای مشکلی پیشنهاد می‌کنید که باید اجرا شود. اینها با نظرات معمولی متفاوت هستند زیرا قابل اجرا هستند. اقدامات عبارتند از: FIXME: -- need to figure this out or TODO: -- need to implement.

  • 18.5 برای حاشیه نویسی مشکلات از // FIXME: استفاده کنید.
    class Calculator extends Abacus {
      constructor() {
        super();

        // FIXME: در اینجا نباید از جهانی استفاده کرد
        total = 0;
      }
    }

  • 18.6 از // TODO: برای حاشیه نویسی راه حل های مشکلات استفاده کنید.
    class Calculator extends Abacus {
      constructor() {
        super();

        // TODO: total باید توسط یک پارامتر گزینه قابل تنظیم باشد
        this.total = 0;
      }
    }

⬆ بازگشت به بالا

فضای سفید

  • 19.1 از زبانه های نرم (نویسه فاصله) با 2 فاصله استفاده کنید. eslint: indent
    // ‎بد
    function foo() {
    ∙∙∙∙let name;
    }

    // ‎بد
    function bar() {
    ∙let name;
    }

    // ‎خوب
    function baz() {
    ∙∙let name;
    }

    // ‎بد
    function test(){
      console.log('test');
    }

    // ‎خوب
    function test() {
      console.log('test');
    }

    // ‎بد
    dog.set('attr',{
      age: '1 year',
      breed: 'Bernese Mountain Dog',
    });

    // ‎خوب
    dog.set('attr', {
      age: '1 year',
      breed: 'Bernese Mountain Dog',
    });

  • 19.3 فاصله قبل از پرانتز آغازین در دستورات کنترل (if، while و غیره) قرار دهید. هیچ فاصله ای بین لیست آرگومان و نام تابع در فراخوانی ها و اعلان های تابع قرار ندهید. eslint: keyword-spacing
    // ‎بد
    if(isJedi) {
      fight ();
    }

    // ‎خوب
    if (isJedi) {
      fight();
    }

    // ‎بد
    function fight () {
      console.log ('Swooosh!');
    }

    // ‎خوب
    function fight() {
      console.log('Swooosh!');
    }

    // ‎بد
    const x=y+5;

    // ‎خوب
    const x = y + 5;

  • 19.5 فایل ها را با یک نویسه خط جدید پایان دهید. eslint: eol-last
    // ‎بد
    import { es6 } from './AirbnbStyleGuide';
      // ...
    export default es6;
    // ‎بد
    import { es6 } from './AirbnbStyleGuide';
      // ...
    export default es6;
    
    // ‎خوب
    import { es6 } from './AirbnbStyleGuide';
      // ...
    export default es6;

  • 19.6 هنگام ساخت زنجیرهای متد بلند (بیش از 2 زنجیره متد) از تورفتگی استفاده کنید. از یک نقطه پیشرو استفاده کنید که تاکید می کند که خط یک فراخوانی متد است، نه یک دستور جدید.
    eslint: newline-per-chained-call no-whitespace-before-property
    // ‎بد
    $('#items').find('.selected').highlight().end().find('.open').updateCount();

    // ‎بد
    $('#items').
      find('.selected').
        highlight().
        end().
      find('.open').
        updateCount();

    // ‎خوب
    $('#items')
      .find('.selected')
        .highlight()
        .end()
      .find('.open')
        .updateCount();

    // ‎بد
    const leds = stage.selectAll('.led').data(data).enter().append('svg:svg').classed('led', true)
        .attr('width', (radius + margin) * 2).append('svg:g')
        .attr('transform', `translate(${radius + margin}, ${radius + margin})`)
        .call(tron.led);

    // ‎خوب
    const leds = stage.selectAll('.led')
        .data(data)
      .enter().append('svg:svg')
        .classed('led', true)
        .attr('width', (radius + margin) * 2)
      .append('svg:g')
        .attr('transform', `translate(${radius + margin}, ${radius + margin})`)
        .call(tron.led);

    // ‎خوب
    const leds = stage.selectAll('.led').data(data);
    const svg = leds.enter().append('svg:svg');
    svg.classed('led', true).attr('width', (radius + margin) * 2);
    const g = svg.append('svg:g');
    g.attr('transform', `translate(${radius + margin}, ${radius + margin})`).call(tron.led);

  • 19.7 بعد از بلوک ها و قبل از عبارت بعدی یک خط خالی بگذارید.
    // ‎بد
    if (foo) {
      return bar;
    }
    return baz;

    // ‎خوب
    if (foo) {
      return bar;
    }

    return baz;

    // ‎بد
    const obj = {
      foo() {
      },
      bar() {
      },
    };
    return obj;

    // ‎خوب
    const obj = {
      foo() {
      },

      bar() {
      },
    };

    return obj;

    // ‎بد
    const arr = [
      function foo() {
      },
      function bar() {
      },
    ];
    return arr;

    // ‎خوب
    const arr = [
      function foo() {
      },

      function bar() {
      },
    ];

    return arr;

  • 19.8 بلوک های خود را با خطوط خالی پر نکنید. eslint: padded-blocks
    // ‎بد
    function bar() {

      console.log(foo);

    }

    // ‎بد
    if (baz) {

      console.log(quux);
    } else {
      console.log(foo);

    }

    // ‎بد
    class Foo {

      constructor(bar) {
        this.bar = bar;
      }
    }

    // ‎خوب
    function bar() {
      console.log(foo);
    }

    // ‎خوب
    if (baz) {
      console.log(quux);
    } else {
      console.log(foo);
    }

  • 19.9 برای اضافه کردن کد خود از چندین خط خالی استفاده نکنید. eslint: no-multiple-empty-lines

    // ‎بد
    class Person {
      constructor(fullName, email, birthday) {
        this.fullName = fullName;


        this.email = email;


        this.setAge(birthday);
      }


      setAge(birthday) {
        const today = new Date();


        const age = this.getAge(today, birthday);


        this.age = age;
      }


      getAge(today, birthday) {
        // ..
      }
    }

    // ‎خوب
    class Person {
      constructor(fullName, email, birthday) {
        this.fullName = fullName;
        this.email = email;
        this.setAge(birthday);
      }

      setAge(birthday) {
        const today = new Date();
        const age = getAge(today, birthday);
        this.age = age;
      }

      getAge(today, birthday) {
        // ..
      }
    }

    // ‎بد
    function bar( foo ) {
      return foo;
    }

    // ‎خوب
    function bar(foo) {
      return foo;
    }

    // ‎بد
    if ( foo ) {
      console.log(foo);
    }

    // ‎خوب
    if (foo) {
      console.log(foo);
    }

    // ‎بد
    const foo = [ 1, 2, 3 ];
    console.log(foo[ 0 ]);

    // ‎خوب
    const foo = [1, 2, 3];
    console.log(foo[0]);

    // ‎بد
    const foo = {clark: 'kent'};

    // ‎خوب
    const foo = { clark: 'kent' };

  • 19.13 از داشتن خطوط کد بیشتر از 100 کاراکتر (شامل فضای خالی) خودداری کنید. توجه: در بالا، رشته های طولانی از این قانون مستثنی هستند و نباید شکسته شوند. eslint: max-len

    چرا؟ این خوانایی و قابلیت نگهداری را تضمین می کند.

    // ‎بد
    const foo = jsonData && jsonData.foo && jsonData.foo.bar && jsonData.foo.bar.baz && jsonData.foo.bar.baz.quux && jsonData.foo.bar.baz.quux.xyzzy;

    // ‎بد
    $.ajax({ method: 'POST', url: 'https://airbnb.com/', data: { name: 'John' } }).done(() => console.log('Congratulations!')).fail(() => console.log('You have failed this city.'));

    // ‎خوب
    const foo = jsonData
      && jsonData.foo
      && jsonData.foo.bar
      && jsonData.foo.bar.baz
      && jsonData.foo.bar.baz.quux
      && jsonData.foo.bar.baz.quux.xyzzy;

    // ‎بهتر
    const foo = jsonData
      ?.foo
      ?.bar
      ?.baz
      ?.quux
      ?.xyzzy;
    // ‎خوب
    $.ajax({
      method: 'POST',
      url: 'https://airbnb.com/',
      data: { name: 'John' },
    })
      .done(() => console.log('Congratulations!'))
      .fail(() => console.log('You have failed this city.'));

  • 19.14 نیاز به فاصله ثابت در داخل یک نشانه بلوک باز و نشانه بعدی در همان خط است. این قانون همچنین فاصله ثابتی را در داخل یک نشانه بلوک نزدیک و توکن قبلی در همان خط اعمال می کند. eslint: block-spacing
    // ‎بد
    function foo() {return true;}
    if (foo) { bar = 0;}

    // ‎خوب
    function foo() { return true; }
    if (foo) { bar = 0; }

  • 19.15 از فاصله قبل از کاما اجتناب کنید و نیاز به فاصله بعد از کاما دارید. eslint: comma-spacing
    // ‎بد
    const foo = 1,bar = 2;
    const arr = [1 , 2];

    // ‎خوب
    const foo = 1, bar = 2;
    const arr = [1, 2];

    // ‎بد
    obj[foo ]
    obj[ 'foo']
    const x = {[ b ]: a}
    obj[foo[ bar ]]

    // ‎خوب
    obj[foo]
    obj['foo']
    const x = { [b]: a }
    obj[foo[bar]]

  • 19.17 از فاصله بین توابع و فراخوانی آنها اجتناب کنید. eslint: func-call-spacing
    // ‎بد
    func ();

    func
    ();

    // ‎خوب
    func();

  • 19.18 اعمال فاصله بین کلیدها و مقادیر در ویژگی های لغوی شیء. eslint: key-spacing
    // ‎بد
    const obj = { foo : 42 };
    const obj2 = { foo:42 };

    // ‎خوب
    const obj = { foo: 42 };

  • 19.19 از فضاهای انتهایی در انتهای خطوط خودداری کنید. eslint: no-trailing-spaces

  • 19.20 از چند خط خالی اجتناب کنید، فقط یک خط جدید در انتهای فایل ها مجاز کنید و از خط جدید در ابتدای فایل ها اجتناب کنید. eslint: no-multiple-empty-lines

    // ‎بد - چندین خط خالی
    const x = 1;


    const y = 2;

    // ‎بد - 2+ خط جدید در انتهای فایل
    const x = 1;
    const y = 2;


    // ‎بد - 1+ خط(های) جدید در ابتدای فایل

    const x = 1;
    const y = 2;

    // ‎خوب
    const x = 1;
    const y = 2;

⬆ بازگشت به بالا

ویرگول ها

    // ‎بد
    const story = [
        once
      , upon
      , aTime
    ];

    // ‎خوب
    const story = [
      once,
      upon,
      aTime,
    ];

    // ‎بد
    const hero = {
        firstName: 'Ada'
      , lastName: 'Lovelace'
      , birthYear: 1815
      , superPower: 'computers'
    };

    // ‎خوب
    const hero = {
      firstName: 'Ada',
      lastName: 'Lovelace',
      birthYear: 1815,
      superPower: 'computers',
    };

  • 20.2 کاما انتهایی اضافی: آره. eslint: comma-dangle

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

    // ‎بد - git diff بدون کاما انتهایی
    const hero = {
         firstName: 'Florence',
    -    lastName: 'Nightingale'
    +    lastName: 'Nightingale',
    +    inventorOf: ['coxcomb chart', 'modern nursing']
    };

    // ‎خوب - git diff با کاما انتهایی
    const hero = {
         firstName: 'Florence',
         lastName: 'Nightingale',
    +    inventorOf: ['coxcomb chart', 'modern nursing'],
    };
    // ‎بد
    const hero = {
      firstName: 'Dana',
      lastName: 'Scully'
    };

    const heroes = [
      'Batman',
      'Superman'
    ];

    // ‎خوب
    const hero = {
      firstName: 'Dana',
      lastName: 'Scully',
    };

    const heroes = [
      'Batman',
      'Superman',
    ];

    // ‎بد
    function createHero(
      firstName,
      lastName,
      inventorOf
    ) {
      // ‎هیچ کاری نمی کند
    }

    // ‎خوب
    function createHero(
      firstName,
      lastName,
      inventorOf,
    ) {
      // ‎هیچ کاری نمی کند
    }

    // ‎خوب (توجه داشته باشید که کاما نباید بعد از عنصر "rest" ظاهر شود)
    function createHero(
      firstName,
      lastName,
      inventorOf,
      ...heroArgs
    ) {
      // ‎هیچ کاری نمی کند
    }

    // ‎بد
    createHero(
      firstName,
      lastName,
      inventorOf
    );

    // ‎خوب
    createHero(
      firstName,
      lastName,
      inventorOf,
    );

    // ‎خوب (توجه داشته باشید که کاما نباید بعد از عنصر "rest" ظاهر شود)
    createHero(
      firstName,
      lastName,
      inventorOf,
      ...heroArgs
    );

⬆ بازگشت به بالا

نقطه ویرگول ها

  • 21.1 آره. eslint: semi

    چرا؟ هنگامی که جاوا اسکریپت با شکست خط بدون نقطه ویرگول مواجه می شود، از مجموعه قوانینی به نام درج خودکار نقطه ویرگول استفاده می کند تا تعیین کند که آیا باید یک خط منتهی در نظر گرفته شود یا خیر. آن خط را به عنوان پایان یک عبارت شکسته و (همانطور که از نام آن پیداست) قبل از خط شکستن یک نقطه ویرگول در کد خود قرار دهید، اگر چنین فکر می کند. با این حال، ASI حاوی چند رفتار غیرعادی است و اگر جاوا اسکریپت شکست خط شما را اشتباه تفسیر کند، کد شما خراب می‌شود. این قوانین با تبدیل شدن ویژگی های جدید به بخشی از جاوا اسکریپت پیچیده تر می شوند. خاتمه دادن صریح عبارات خود و پیکربندی لیتر خود برای گرفتن نقطه ویرگول های گم شده به شما کمک می کند تا با مشکلاتی مواجه نشوید.

    // ‎بد - استثناء ایجاد می کند
    const luke = {}
    const leia = {}
    [luke, leia].forEach((jedi) => jedi.father = 'vader')

    // ‎بد - استثناء ایجاد می کند
    const reaction = "No! That’s impossible!"
    (async function meanwhileOnTheFalcon() {
      // ‎handle `leia`, `lando`, `chewie`, `r2`, `c3p0`
      // ...
    }())

    // ‎بد - به جای مقدار خط بعدی، `undefined` را برمی گرداند - همیشه زمانی اتفاق می افتد که `return` به خودی خود به دلیل ASI روی یک خط باشد!
    function foo() {
      return
        'search your feelings, you know it to be foo'
    }

    // ‎خوب
    const luke = {};
    const leia = {};
    [luke, leia].forEach((jedi) => {
      jedi.father = 'vader';
    });

    // ‎خوب
    const reaction = 'No! That’s impossible!';
    (async function meanwhileOnTheFalcon() {
      // ‎رسیدگی به `leia`, `lando`, `chewie`, `r2`, `c3p0`
      // ...
    }());

    // ‎خوب
    function foo() {
      return 'search your feelings, you know it to be foo';
    }

بیشتر بخوانید.

⬆ بازگشت به بالا

نوع ریختگی و اجبار

  • 22.1 اجبار نوع را در ابتدای بیانیه انجام دهید.

    // => this.reviewScore = 9;

    // ‎بد
    const totalScore = new String(this.reviewScore); // ‎نوع totalScore "object" است نه  "string"

    // ‎بد
    const totalScore = this.reviewScore + ''; // ‎فراخوانی می کند this.reviewScore.valueOf()

    // ‎بد
    const totalScore = this.reviewScore.toString(); // ‎تضمینی برای بازگرداندن یک رشته نیست

    // ‎خوب
    const totalScore = String(this.reviewScore);

  • 22.3 اعداد: از Number برای ریختن نوع و از parseInt همیشه با یک ریشه برای تجزیه رشته ها استفاده کنید. eslint: radix no-new-wrappers

    چرا؟ تابع 'parseInt' یک مقدار صحیح تولید می کند که توسط تفسیر محتویات آرگومان رشته با توجه به ریشه مشخص شده دیکته می شود. فضای سفید پیشرو در رشته نادیده گرفته می شود. اگر ریشه undefined یا 0 باشد، 10 در نظر گرفته می‌شود، به جز زمانی که عدد با جفت‌های کاراکتر 0x یا 0X شروع می‌شود، در این صورت، ریشه 16 در نظر گرفته می‌شود. این با ECMAScript 3 متفاوت است، که صرفاً تفسیر اکتالی را منع می کرد (اما مجاز می دانست). بسیاری از پیاده‌سازی‌ها از سال 2013 این رفتار را اتخاذ نکرده‌اند. و چون مرورگرهای قدیمی‌تر باید پشتیبانی شوند، همیشه یک رادیکس مشخص کنید.

    const inputValue = '4';

    // ‎بد
    const val = new Number(inputValue);

    // ‎بد
    const val = +inputValue;

    // ‎بد
    const val = inputValue >> 0;

    // ‎بد
    const val = parseInt(inputValue);

    // ‎خوب
    const val = Number(inputValue);

    // ‎خوب
    const val = parseInt(inputValue, 10);

  • 22.4 اگر به هر دلیلی در حال انجام کاری غرمعمول هستید و parseInt تنگنای شماست و به دلیل دلایل عملکرد باید از Bitshift استفاده کنید، یک نظر بگذارید و توضیح دهید که چرا و چه کاری انجام می دهید.
    // ‎خوب
    /**
     * parseInt دلیل کند بودن کد من بود.
     * Bitshifting رشته برای وادار کردن آن به یک عدد آن را بسیار سریعتر کرد.
     */
    const val = inputValue >> 0;

  • 22.5 نکته: هنگام استفاده از عملیات bitshift مراقب باشید. اعداد به صورت مقادیر 64 بیتی نشان داده می شوند، اما عملیات bitshift همیشه یک عدد صحیح 32 بیتی (source). Bitshift می تواند منجر به رفتار غیرمنتظره برای مقادیر صحیح بزرگتر از 32 بیت شود. بحث. بزرگترین Int 32 بیتی امضا شده 2,147,483,647 است:
    2147483647 >> 0; // => 2147483647
    2147483648 >> 0; // => -2147483648
    2147483649 >> 0; // => -2147483647

    const age = 0;

    // ‎بد
    const hasAge = new Boolean(age);

    // ‎خوب
    const hasAge = Boolean(age);

    // ‎بهترین
    const hasAge = !!age;

⬆ بازگشت به بالا

قراردادهای نامگذاری

  • 23.1 از نام های تک حرفی خودداری کنید. در نامگذاری توصیفی تر باشید. eslint: id-length
    // ‎بد
    function q() {
      // ...
    }
    // ‎خوب
    function query() {
      // ...
    }

  • 23.2 هنگام نامگذاری اشیا، توابع و نمونه ها از camelCase استفاده کنید. eslint: camelcase
    // ‎بد
    const OBJEcttsssss = {};
    const this_is_my_object = {};
    function c() {}
    // ‎خوب
    const thisIsMyObject = {};
    function thisIsMyFunction() {}

  • 23.3 فقط هنگام نامگذاری سازنده ها یا کلاس ها از PascalCase استفاده کنید. eslint: new-cap
    // ‎بد
    function user(options) {
      this.name = options.name;
    }

    const bad = new user({
      name: 'nope',
    });
    // ‎خوب
    class User {
      constructor(options) {
        this.name = options.name;
      }
    }

    const good = new User({
      name: 'yup',
    });

  • 23.4 از زیرخط های انتهایی یا پیشرو استفاده نکنید. eslint: no-underscore-dangle

    چرا؟ جاوا اسکریپت از نظر ویژگی ها یا روش ها مفهوم حریم خصوصی را ندارد. اگر چه یک زیرخط پیشرو یک قرارداد رایج به معنای “private” است، اما در واقع، این ویژگی‌ها کاملاً عمومی هستند و به این ترتیب، بخشی از قرارداد عمومی API شما هستند. این قرارداد ممکن است باعث شود توسعه دهندگان به اشتباه فکر کنند که تغییر به عنوان شکستگی به حساب نمی آید، یا آزمایش هایی لازم نیست. کوتاه بگوییم: اگر می‌خواهید چیزی “private” باشد، نباید به‌طور قابل مشاهده وجود داشته باشد.

    // بد
    this.__firstName__ = 'Panda';
    this.firstName_ = 'Panda';
    this._firstName = 'Panda';

    // ‎خوب
    this.firstName = 'Panda';

    // ‎خوب، در محیط هایی که WeakMaps در دسترس است
    // ‎مشاهده کنید در https://kangax.github.io/compat-table/es6/#test-WeakMap
    const firstNames = new WeakMap();
    firstNames.set(this, 'Panda');

  • 23.5 ارجاعات به this را ذخیره نکنید. از توابع پیکان یا Function#bind استفاده کنید.
    // ‎بد
    function foo() {
      const self = this;
      return function () {
        console.log(self);
      };
    }

    // ‎بد
    function foo() {
      const that = this;
      return function () {
        console.log(that);
      };
    }

    // ‎خوب
    function foo() {
      return () => {
        console.log(this);
      };
    }

  • 23.6 نام فایل پایه باید دقیقاً با نام export پیش فرض آن مطابقت داشته باشد.
    // ‎محتویات فایل 1
    class CheckBox {
      // ...
    }
    export default CheckBox;

    // ‎محتویات فایل 2
    export default function fortyTwo() { return 42; }

    // ‎محتویات فایل 3
    export default function insideDirectory() {}

    // ‎در یک فایل دیگر
    // ‎بد
    import CheckBox from './checkBox'; // PascalCase import/export, camelCase filename
    import FortyTwo from './FortyTwo'; // PascalCase import/filename, camelCase export
    import InsideDirectory from './InsideDirectory'; // PascalCase import/filename, camelCase export

    // ‎بد
    import CheckBox from './check_box'; // PascalCase import/export, snake_case filename
    import forty_two from './forty_two'; // snake_case import/filename, camelCase export
    import inside_directory from './inside_directory'; // snake_case import, camelCase export
    import index from './inside_directory/index'; // requiring the index file explicitly
    import insideDirectory from './insideDirectory/index'; // requiring the index file explicitly

    // ‎خوب
    import CheckBox from './CheckBox'; // PascalCase export/import/filename
    import fortyTwo from './fortyTwo'; // camelCase export/import/filename
    import insideDirectory from './insideDirectory'; // camelCase export/import/directory name/implicit "index"
    // ^ از insideDirectory.js و insideDirectory/index.js پشتیبانی می کند

  • 23.7 هنگام صادرات-پیش‌فرض (export-default) یک تابع، از camelCase استفاده کنید. نام فایل شما باید با نام تابع شما یکسان باشد.
    function makeStyleGuide() {
      // ...
    }

    export default makeStyleGuide;

  • 23.8 هنگامی که یک سازنده / کلاس / تک تن / کتابخانه تابع / شیء خالی را صادر می کنید از PascalCase استفاده کنید.
    const AirbnbStyleGuide = {
      es6: {
      },
    };

    export default AirbnbStyleGuide;

  • 23.9 حروف اختصاری و حروف اولیه باید همیشه با حروف بزرگ یا کوچک باشند.

    چرا؟ نام ها برای خوانایی هستند، نه برای کمک کردن به مماشات یک الگوریتم رایانه ای.

    // ‎بد
    import SmsContainer from './containers/SmsContainer';

    // ‎بد
    const HttpRequests = [
      // ...
    ];

    // ‎خوب
    import SMSContainer from './containers/SMSContainer';

    // ‎خوب
    const HTTPRequests = [
      // ...
    ];

    // ‎هچنان خوب
    const httpRequests = [
      // ...
    ];

    // ‎بهترین
    import TextMessageContainer from './containers/TextMessageContainer';

    // ‎بهترین
    const requests = [
      // ...
    ];

  • 23.10 شما می توانید به صورت اختیاری یک ثابت را با حروف بزرگ فقط در صورتی که (1) صادر شده باشد، (2) یک 'const' باشد (نمی توان آن را دوباره اختصاص داد)، و (3) برنامه نویس می تواند به آن (و خصوصیات تودرتوی آن) اعتماد کند تا هرگز تغییر نکند.

    چرا؟ این یک ابزار اضافی برای کمک به شرایطی است که برنامه نویس مطمئن نیست که آیا متغیری ممکن است تغییر کند. UPPERCASE_VARIABLES به برنامه نویس اجازه می دهد بداند که می تواند به تغییر نکردن متغیر (و خصوصیات آن) اعتماد کند.

    • در مورد همه متغیرهای 'const' چطور؟ - این غیر ضروری است، بنابراین نباید از حروف بزرگ برای ثابت های داخل یک فایل استفاده کرد. اما باید برای ثابت های صادر شده استفاده شود.
    • در مورد اشیاء صادراتی چطور؟ - حروف بزرگ در سطح بالای صادرات (به عنوان مثال EXPORTED_OBJECT.key) و حفظ کنید که همه ویژگی‌های تودرتو تغییر نمی‌کنند.
    // ‎بد
    const PRIVATE_VARIABLE = 'should not be unnecessarily uppercased within a file';

    // ‎بد
    export const THING_TO_BE_CHANGED = 'should obviously not be uppercased';

    // ‎بد
    export let REASSIGNABLE_VARIABLE = 'do not use let with uppercase variables';

    // ---

    // ‎مجاز است اما ارزش معنایی را ارائه نمی کند
    export const apiKey = 'SOMEKEY';

    // ‎در بیشتر موارد بهتر است
    export const API_KEY = 'SOMEKEY';

    // ---

    // ‎بد - نیاز نبدون به حروف بزرگ کلید در حالی که هیچ ارزش معنایی اضافه نمی کند
    export const MAPPING = {
      KEY: 'value'
    };

    // ‎خوب
    export const MAPPING = {
      key: 'value',
    };

⬆ بازگشت به بالا

دسترسی گیرنده / دهنده ها

  • 24.1 توابع Accessor برای خواص مورد نیاز نیست.

  • 24.2 از دریافت کننده/تنظیم کننده های جاوا اسکریپت استفاده نکنید زیرا باعث ایجاد عوارض جانبی غیرمنتظره می شوند و آزمایش، نگهداری و استدلال در مورد آنها سخت تر است. در عوض، اگر توابع دسترسی را ایجاد می‌کنید، از ()getVal و ("سلام")setVal استفاده کنید.
    // ‎بد
    class Dragon {
      get age() {
        // ...
      }

      set age(value) {
        // ...
      }
    }

    // ‎خوب
    class Dragon {
      getAge() {
        // ...
      }

      setAge(value) {
        // ...
      }
    }

  • 24.3 اگر ویژگی/متدی boolean است، از ()isVal یا ()hasVal استفاده کنید.
    // ‎بد
    if (!dragon.age()) {
      return false;
    }

    // ‎خوب
    if (!dragon.hasAge()) {
      return false;
    }

  • 24.4 ایجاد توابع ()get و ()set اشکالی ندارد، اما سازگار باشید.
    class Jedi {
      constructor(options = {}) {
        const lightsaber = options.lightsaber || 'blue';
        this.set('lightsaber', lightsaber);
      }

      set(key, val) {
        this[key] = val;
      }

      get(key) {
        return this[key];
      }
    }

⬆ بازگشت به بالا

رویدادها

  • 25.1 هنگام پیوست کردن محموله‌های داده به رویدادها (چه رویدادهای DOM یا چیزهای اختصاصی‌تر مانند رویدادهای Backbone)، به جای مقدار خام، یک شیء را به صورت تحت اللفظی (همچنین به عنوان "hash" شناخته می‌شود) ارسال کنید. این به مشارکت‌کننده بعدی اجازه می‌دهد تا داده‌های بیشتری را بدون یافتن و به‌روزرسانی هر کنترل‌کننده رویداد به بار رویداد اضافه کند. به عنوان مثال، به جای:
    // ‎بد
    $(this).trigger('listingUpdated', listing.id);

    // ...

    $(this).on('listingUpdated', (e, listingID) => {
      // ‎عملیاتی با listingID
    });

ترجیح بدهید:

    // ‎خوب
    $(this).trigger('listingUpdated', { listingID: listing.id });

    // ...

    $(this).on('listingUpdated', (e, data) => {
      // ‎عملیاتی با data.listingID
    });

⬆ بازگشت به بالا

جی کوئری

  • 26.1 متغیرهای شیء jQuery را با یک $ پیشوند کنید.
    // ‎بد
    const sidebar = $('.sidebar');

    // ‎خوب
    const $sidebar = $('.sidebar');

    // ‎خوب
    const $sidebarBtn = $('.sidebar-btn');

  • 26.2 جستجوهای jQuery را ذخیره کنید.
    // ‎بد
    function setSidebar() {
      $('.sidebar').hide();

      // ...

      $('.sidebar').css({
        'background-color': 'pink',
      });
    }

    // ‎خوب
    function setSidebar() {
      const $sidebar = $('.sidebar');
      $sidebar.hide();

      // ...

      $sidebar.css({
        'background-color': 'pink',
      });
    }

  • 26.3 برای جستارهای DOM از $('.sidebar ul') آبشاری یا والد > فرزند $('.sidebar > ul') استفاده کنید. jsPerf

  • 26.4 از find با پرس و جوهای شیء jQuery با محدوده استفاده کنید.
    // ‎بد
    $('ul', '.sidebar').hide();

    // ‎بد
    $('.sidebar').find('ul').hide();

    // ‎خوب
    $('.sidebar ul').hide();

    // ‎خوب
    $('.sidebar > ul').hide();

    // ‎خوب
    $sidebar.find('ul').hide();

⬆ بازگشت به بالا

سازگاری با ECMAScript 5

⬆ بازگشت به بالا

سبک های ECMAScript 6+ (ES 2015+)

  • 28.1 این مجموعه ای از پیوندها به ویژگی های مختلف ES6+ است.
  1. توابع پیکانی
  2. کلاس ها
  3. مخفف شیء ها
  4. شیء مختصر
  5. ویژگی های محاسبه شده شیء
  6. رشته های الگویی
  7. استخراج کردن(destructuring)
  8. پارامترهای پیش فرض
  9. رست(Rest)
  10. گسترش آرایه
  11. متغییر های Let و Const
  12. اپراتور توان
  13. تکرار کننده ها و مولدها
  14. ماژول ها

  • 28.2 از پیشنهادات TC39 که به مرحله 3 نرسیده‌اند استفاده نکنید.

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

⬆ بازگشت به بالا

کتابخانه استاندارد

کتابخانه استاندارد شامل ابزارهایی است که از نظر عملکردی خراب هستند اما به دلایل قدیمی باقی می مانند.

  • 29.1 از Number.isNaN به جای isNaN جهانی استفاده کنید. eslint: 'no-restricted-globals'

    چرا؟ isNaN جهانی، غیر اعداد را به اعداد وادار می‌کند، و برای هر چیزی که به NaN وادار می‌شود، true برمی‌گردد. اگر این رفتار مورد نظر است، آن را به صراحت بیان کنید.

    // ‎بد
    isNaN('1.2'); // false
    isNaN('1.2.3'); // true

    // ‎خوب
    Number.isNaN('1.2.3'); // false
    Number.isNaN(Number('1.2.3')); // true

  • 29.2 از Number.isFinite به جای isFinite سراسری استفاده کنید. eslint: 'no-restricted-globals'

    چرا؟ isFinite سراسری، غیر اعداد را به اعداد وادار می کند، و برای هر چیزی که به یک عدد متناهی وادار می شود، true برمی گردد. اگر این رفتار مورد نظر است، آن را به صراحت بیان کنید.

    // ‎بد
    isFinite('2e3'); // true

    // ‎خوب
    Number.isFinite('2e3'); // false
    Number.isFinite(parseInt('2e3', 10)); // true

⬆ بازگشت به بالا

آزمایش کردن

    function foo() {
      return true;
    }

  • 30.2 نه ولی جدی:
    • از هر چارچوب تستی که استفاده می کنید، باید تست بنویسید!
    • سعی کنید بسیاری از توابع خالص کوچک را بنویسید و مکان هایی که جهش ها رخ می دهند را به حداقل برسانید.
    • در مورد موارد خرد و تمسخر محتاط باشید - آنها می توانند تست های شما را شکننده تر کنند.
    • ما در اصل از mocha و jest در Airbnb استفاده می کنیم. 'tape' نیز گهگاه برای ماژول های کوچک و جداگانه استفاده می شود.
    • پوشش 100% آزمون هدف خوبی برای تلاش کردن است، حتی اگر رسیدن به آن همیشه عملی نباشد.
    • هر زمان که اشکالی را برطرف کردید، یک تست رگرسیون بنویسید. باگ رفع شده بدون تست رگرسیون تقریباً مطمئناً در آینده دوباره از بین خواهد رفت.

⬆ بازگشت به بالا

کارایی

⬆ بازگشت به بالا

منابع

یادگیری ES6+

این را بخوانید

ابزارها

سایر راهنماهای سبک کد

سبک های دیگر

بیشتر خواندن

کتاب ها

وبلاگ ها

پادکست ها

⬆ بازگشت به بالا

موارد استفاده در دنیای واقعی

این لیستی از سازمان هایی است که از این راهنمای سبک استفاده می کنند. یک درخواست pull برای ما ارسال کنید و ما شما را به لیست اضافه خواهیم کرد.

⬆ بازگشت به بالا

ترجمه

این راهنمای سبک به زبان های دیگر نیز موجود است:

راهنمای راهنمای سبک جاوا اسکریپت

درباره جاوا اسکریپت با ما گپ بزنید

  • ما را در gitter پیدا کنید.

مشارکت کنندگان

مجوز

(مجوز MIT)

Copyright (c) 2012 Airbnb

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

⬆ بازگشت به بالا

اصلاحیه ها

ما شما را تشویق می کنیم که این راهنما را fork کنید و قوانین را متناسب با راهنمای سبک تیم خود تغییر دهید. در زیر، ممکن است برخی از اصلاحات در راهنمای سبک را فهرست کنید. این به شما این امکان را می دهد که به طور دوره ای راهنمای سبک خود را بدون نیاز به مقابله با تضادهای ادغام به روز کنید.

;{