نهج معقول في الغالب لجافا سكريبت
ملاحظة : يفترض هذا الدليل أنك تستخدم Babel، ويتطلب استخدام babel-preset-airbnb أو ما يعادله. ويفترض أيضًا أنك تقوم بتثبيت الحشوات/الحشوات المتعددة في تطبيقك، باستخدام airbnb-browser-shims أو ما يعادله.
هذا الدليل متاح بلغات أخرى أيضًا. انظر الترجمة
أدلة نمط أخرى
1.1 البدائيات : عند الوصول إلى نوع بدائي، فإنك تعمل مباشرة على قيمته.
string
number
boolean
null
undefined
symbol
bigint
const foo = 1 ;
let bar = foo ;
bar = 9 ;
console . log ( foo , bar ) ; // => 1, 9
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
لماذا؟ يضمن ذلك عدم إمكانية إعادة تعيين مراجعك، مما قد يؤدي إلى حدوث أخطاء وصعوبة فهم التعليمات البرمجية.
// bad
var a = 1 ;
var b = 2 ;
// good
const a = 1 ;
const b = 2 ;
2.2 إذا كان يجب عليك إعادة تعيين المراجع، فاستخدم let
بدلاً من var
. إسلينت: no-var
لماذا؟
let
يتم تحديد نطاقه على نطاق الكتلة بدلاً من نطاق الوظيفة مثلvar
.
// bad
var count = 1 ;
if ( true ) {
count += 1 ;
}
// good, use the let.
let count = 1 ;
if ( true ) {
count += 1 ;
}
2.3 لاحظ أن كلا من let
و const
مُحددان بنطاق الكتلة، في حين أن var
مُحدد بنطاق الوظيفة.
// const and let only exist in the blocks they are defined in.
{
let a = 1 ;
const b = 1 ;
var c = 1 ;
}
console . log ( a ) ; // ReferenceError
console . log ( b ) ; // ReferenceError
console . log ( c ) ; // Prints 1
في الكود أعلاه، يمكنك أن ترى أن الإشارة إلى a
و b
ستؤدي إلى خطأ مرجعي، بينما يحتوي c
على الرقم. وذلك لأن a
و b
محددان للكتلة، بينما c
محددان للوظيفة المحتوية.
⬆ العودة إلى الأعلى
3.1 استخدم الصيغة الحرفية لإنشاء الكائن. eslint: no-new-object
// bad
const item = new Object ( ) ;
// good
const item = { } ;
3.2 استخدم أسماء الخصائص المحسوبة عند إنشاء كائنات بأسماء خصائص ديناميكية.
لماذا؟ إنها تسمح لك بتحديد جميع خصائص الكائن في مكان واحد.
function getKey ( k ) {
return `a key named ${ k } ` ;
}
// bad
const obj = {
id : 5 ,
name : 'San Francisco' ,
} ;
obj [ getKey ( 'enabled' ) ] = true ;
// good
const obj = {
id : 5 ,
name : 'San Francisco' ,
[ getKey ( 'enabled' ) ] : true ,
} ;
3.3 استخدام طريقة الكائن المختصرة. eslint: object-shorthand
// bad
const atom = {
value : 1 ,
addValue : function ( value ) {
return atom . value + value ;
} ,
} ;
// good
const atom = {
value : 1 ,
addValue ( value ) {
return atom . value + value ;
} ,
} ;
3.4 استخدم اختصار قيمة الخاصية. eslint: object-shorthand
لماذا؟ وهي أقصر ووصفية.
const lukeSkywalker = 'Luke Skywalker' ;
// bad
const obj = {
lukeSkywalker : lukeSkywalker ,
} ;
// good
const obj = {
lukeSkywalker ,
} ;
3.5 قم بتجميع خصائص الاختزال الخاصة بك في بداية إعلان الكائن الخاص بك.
لماذا؟ من الأسهل معرفة الخصائص التي تستخدم الاختصار.
const anakinSkywalker = 'Anakin Skywalker' ;
const lukeSkywalker = 'Luke Skywalker' ;
// bad
const obj = {
episodeOne : 1 ,
twoJediWalkIntoACantina : 2 ,
lukeSkywalker ,
episodeThree : 3 ,
mayTheFourth : 4 ,
anakinSkywalker ,
} ;
// good
const obj = {
lukeSkywalker ,
anakinSkywalker ,
episodeOne : 1 ,
twoJediWalkIntoACantina : 2 ,
episodeThree : 3 ,
mayTheFourth : 4 ,
} ;
3.6 خصائص الاقتباس التي تعتبر معرفات غير صالحة فقط. eslint: quote-props
لماذا؟ بشكل عام، نحن نعتبره أسهل للقراءة بشكل شخصي. إنه يعمل على تحسين تمييز بناء الجملة، ويتم تحسينه أيضًا بسهولة أكبر بواسطة العديد من محركات JS.
// bad
const bad = {
'foo' : 3 ,
'bar' : 4 ,
'data-blah' : 5 ,
} ;
// good
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)
). في المتصفحات الحديثة التي تدعم ES2022، أو مع polyfill مثل https://npmjs.com/object.hasown، يمكن أيضًا استخدامObject.hasOwn
كبديل لـObject.prototype.hasOwnProperty.call
.
// bad
console . log ( object . hasOwnProperty ( key ) ) ;
// good
console . log ( Object . prototype . hasOwnProperty . call ( object , key ) ) ;
// better
const has = Object . prototype . hasOwnProperty ; // cache the lookup once, in module scope.
console . log ( has . call ( object , key ) ) ;
// best
console . log ( Object . hasOwn ( object , key ) ) ; // only supported in browsers that support ES2022
/* or */
import has from 'has' ; // https://www.npmjs.com/package/has
console . log ( has ( object , key ) ) ;
/* or */
console . log ( Object . hasOwn ( object , key ) ) ; // https://www.npmjs.com/package/object.hasown
3.8 تفضيل بناء جملة الكائن المنتشر على Object.assign
للكائنات ذات النسخ الضحلة. استخدم بناء جملة معلمة استراحة الكائن للحصول على كائن جديد مع حذف خصائص معينة. eslint: prefer-object-spread
// very bad
const original = { a : 1 , b : 2 } ;
const copy = Object . assign ( original , { c : 3 } ) ; // this mutates `original` ಠ_ಠ
delete copy . a ; // so does this
// bad
const original = { a : 1 , b : 2 } ;
const copy = Object . assign ( { } , original , { c : 3 } ) ; // copy => { a: 1, b: 2, c: 3 }
// good
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 }
⬆ العودة إلى الأعلى
4.1 استخدم الصيغة الحرفية لإنشاء المصفوفة. eslint: no-array-constructor
// bad
const items = new Array ( ) ;
// good
const items = [ ] ;
4.2 استخدم Array#push بدلاً من التعيين المباشر لإضافة عناصر إلى مصفوفة.
const someStack = [ ] ;
// bad
someStack [ someStack . length ] = 'abracadabra' ;
// good
someStack . push ( 'abracadabra' ) ;
4.3 استخدم فروق المصفوفات ...
لنسخ المصفوفات.
// bad
const len = items . length ;
const itemsCopy = [ ] ;
let i ;
for ( i = 0 ; i < len ; i += 1 ) {
itemsCopy [ i ] = items [ i ] ;
}
// good
const itemsCopy = [ ... items ] ;
4.4 لتحويل كائن قابل للتكرار إلى مصفوفة، استخدم الحيزات ...
بدلاً من Array.from
const foo = document . querySelectorAll ( '.foo' ) ;
// good
const nodes = Array . from ( foo ) ;
// best
const nodes = [ ... foo ] ;
4.5 استخدم Array.from
لتحويل كائن يشبه المصفوفة إلى مصفوفة.
const arrLike = { 0 : 'foo' , 1 : 'bar' , 2 : 'baz' , length : 3 } ;
// bad
const arr = Array . prototype . slice . call ( arrLike ) ;
// good
const arr = Array . from ( arrLike ) ;
4.6 استخدم Array.from
بدلاً من الانتشار ...
لرسم الخرائط على العناصر التكرارية، لأنه يتجنب إنشاء مصفوفة متوسطة.
// bad
const baz = [ ... foo ] . map ( bar ) ;
// good
const baz = Array . from ( foo , bar ) ;
4.7 استخدم عبارات الإرجاع في عمليات الاسترجاعات الخاصة بأسلوب المصفوفة. لا بأس بحذف الإرجاع إذا كان نص الدالة يتكون من عبارة واحدة تُرجع تعبيرًا بدون آثار جانبية، بعد 8.2. eslint: array-callback-return
// good
[ 1 , 2 , 3 ] . map ( ( x ) => {
const y = x + 1 ;
return x * y ;
} ) ;
// good
[ 1 , 2 , 3 ] . map ( ( x ) => x + 1 ) ;
// bad - no returned value means `acc` becomes undefined after the first iteration
[ [ 0 , 1 ] , [ 2 , 3 ] , [ 4 , 5 ] ] . reduce ( ( acc , item , index ) => {
const flatten = acc . concat ( item ) ;
} ) ;
// good
[ [ 0 , 1 ] , [ 2 , 3 ] , [ 4 , 5 ] ] . reduce ( ( acc , item , index ) => {
const flatten = acc . concat ( item ) ;
return flatten ;
} ) ;
// bad
inbox . filter ( ( msg ) => {
const { subject , author } = msg ;
if ( subject === 'Mockingbird' ) {
return author === 'Harper Lee' ;
} else {
return false ;
}
} ) ;
// good
inbox . filter ( ( msg ) => {
const { subject , author } = msg ;
if ( subject === 'Mockingbird' ) {
return author === 'Harper Lee' ;
}
return false ;
} ) ;
4.8 استخدم فواصل الأسطر بعد فتح أقواس المصفوفة وقبل إغلاق أقواس المصفوفة، إذا كان المصفوفة تحتوي على أسطر متعددة
// bad
const arr = [
[ 0 , 1 ] , [ 2 , 3 ] , [ 4 , 5 ] ,
] ;
const objectInArray = [ {
id : 1 ,
} , {
id : 2 ,
} ] ;
const numberInArray = [
1 , 2 ,
] ;
// good
const arr = [ [ 0 , 1 ] , [ 2 , 3 ] , [ 4 , 5 ] ] ;
const objectInArray = [
{
id : 1 ,
} ,
{
id : 2 ,
} ,
] ;
const numberInArray = [
1 ,
2 ,
] ;
⬆ العودة إلى الأعلى
5.1 استخدم تدمير الكائن عند الوصول إلى خصائص متعددة للكائن واستخدامها. eslint: prefer-destructuring
لماذا؟ يوفر عليك التدمير إنشاء مراجع مؤقتة لتلك الخصائص، ومن الوصول المتكرر للكائن. يؤدي تكرار الوصول إلى الكائنات إلى إنشاء المزيد من التعليمات البرمجية المتكررة، ويتطلب المزيد من القراءة، ويخلق المزيد من الفرص للأخطاء. يوفر تدمير الكائنات أيضًا موقعًا واحدًا لتعريف بنية الكائن المستخدمة في الكتلة، بدلاً من طلب قراءة الكتلة بأكملها لتحديد ما سيتم استخدامه.
// bad
function getFullName ( user ) {
const firstName = user . firstName ;
const lastName = user . lastName ;
return ` ${ firstName } ${ lastName } ` ;
}
// good
function getFullName ( user ) {
const { firstName , lastName } = user ;
return ` ${ firstName } ${ lastName } ` ;
}
// best
function getFullName ( { firstName , lastName } ) {
return ` ${ firstName } ${ lastName } ` ;
}
5.2 استخدام تدمير المصفوفة. eslint: prefer-destructuring
const arr = [ 1 , 2 , 3 , 4 ] ;
// bad
const first = arr [ 0 ] ;
const second = arr [ 1 ] ;
// good
const [ first , second ] = arr ;
5.3 استخدم تدمير الكائنات لقيم الإرجاع المتعددة، وليس تدمير المصفوفة.
لماذا؟ يمكنك إضافة خصائص جديدة بمرور الوقت أو تغيير ترتيب الأشياء دون تعطيل مواقع الاتصال.
// bad
function processInput ( input ) {
// then a miracle occurs
return [ left , right , top , bottom ] ;
}
// the caller needs to think about the order of return data
const [ left , __ , top ] = processInput ( input ) ;
// good
function processInput ( input ) {
// then a miracle occurs
return { left , right , top , bottom } ;
}
// the caller selects only the data they need
const { left , top } = processInput ( input ) ;
⬆ العودة إلى الأعلى
6.1 استخدم علامات الاقتباس المفردة ''
للسلاسل. إسلينت: quotes
// bad
const name = "Capt. Janeway" ;
// bad - template literals should contain interpolation or newlines
const name = `Capt. Janeway` ;
// good
const name = 'Capt. Janeway' ;
6.2 لا ينبغي كتابة السلاسل النصية التي تتسبب في تجاوز السطر أكثر من 100 حرف عبر أسطر متعددة باستخدام تسلسل السلسلة.
لماذا؟ يعد التعامل مع السلاسل المكسورة أمرًا مؤلمًا وتجعل الكود أقل قابلية للبحث.
// bad
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.' ;
// bad
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.' ;
// good
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
لماذا؟ تمنحك سلاسل القالب بنية موجزة وقابلة للقراءة مع الأسطر الجديدة المناسبة وميزات استيفاء السلسلة.
// 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 } ?` ;
}
eval()
على سلسلة نصية؛ فإنه يفتح الكثير من نقاط الضعف. إسلينت: no-eval
6.5 لا تقم بالهروب من الأحرف في السلاسل دون داعٍ. eslint: no-useless-escape
لماذا؟ خطوط مائلة عكسية