Javascript
Một cách tiếp cận hợp lý đối với JavaScript - @Airbnb
Các Kiểu giá trị
1.1 Kiểu nguyên thủy: Khi bạn truy cập một giá trị kiểu nguyên thủy, bạn làm việc trực tiếp trên giá trị của nó.string
number
boolean
null
undefined
symbol
Sự thiếu hỗ trợ cho các
Symbol
không thể được lấp đầy bởi các bộ trợ năng một cách toàn diện, do đó, chúng không nên được sử dụng khi hướng đến các trình duyệt/môi trường không có hỗ trợ sẵn.
1.2 Kiểu phức tạp: Khi bạn truy cập một giá trị kiểu phức tạp, bạn làm việc trên tham chiếu giá trị của nó.
object
array
function
Các Tham chiếu
2.1 Sử dụng
const
đối với tất cả các tham chiếu; tránh sử dụngvar
. eslint:prefer-const
,no-const-assign
Tại sao? Điều này đảm bảo rằng bạn không thể gán lại các tham chiếu, việc có thể gây ra các lỗi và gây khó khăn cho sự đọc hiểu mã nguồn.
2.2 Nếu bạn bắt buộc phải gán lại các tham chiếu, sử dụng
let
, thay vìvar
. eslint:no-var
Tại sao?
let
thuộc phạm vi khối mà nó được khởi tạo, thay vì thuộc phạm vi hàm nhưvar
.2.3 Lưu ý rằng cả
let
vàconst
đều thuộc phạm vi khối.
Các Đối tượng
3.1 Sử dụng cú pháp nguyên văn
{}
để khởi tạo đối tượng. eslint:no-new-object
3.2 Sử dụng các tên được tính của thuộc tính
[key()]
khi tạo các đối tượng có các tên của thuộc tính là động.Tại sao? Chúng cho phép bạn định nghĩa tất cả các thuộc tính của một đối tượng cùng một chỗ.
3.3 Sử dụng cú pháp định nghĩa phương thức rút gọn để định nghĩa các phương thức của đối tượng. eslint:
object-shorthand
3.4 Sử dụng cú pháp định nghĩa thuộc tính rút gọn để định nghĩa các thuộc tính của đối tượng. eslint:
object-shorthand
Tại sao? Nó ngắn gọn và súc tích.
3.5 Gom tất cả các thuộc tính rút gọn ở trên cùng khi khai báo đối tượng.
Tại sao? Điều này giúp bạn dễ dàng biết được thuộc tính nào sử dụng cú pháp rút gọn.
3.6 Chỉ sử dụng dấu lược
' '
cho các thuộc tính có định danh không hợp lệ. eslint:quote-props
Tại sao? Nhìn chung, chúng ta sẽ thấy nó dễ đọc hơn nhiều. Nó cải thiện nhấn mạnh cú pháp, và nó cũng giúp việc tối ưu hóa bằng các trình thực thi JS hiệu quả hơn.
3.7 Không gọi các phương thức
Object.prototype
một cách trực tiếp, ví dụ nhưhasOwnProperty
,propertyIsEnumerable
, vàisPrototypeOf
. eslint:no-prototype-builtins
Tại sao? Những phương thức này có thể bị thay thế bởi các thuộc tính của một đối tượng - như
{ hasOwnProperty: false }
- hoặc, đối tượng có thể là một đối tượng rỗng (Object.create(null)
).3.8 Ưu tiên sử dụng toán tử liệt kê
...
so vớiObject.assign
để tạo bản sao nhanh của một đối tượng. Sử dụng toán tử còn-lại...
để tạo một đối tượng mới với một số thuộc tính đã bị loại bỏ
Các Mảng
4.1 Sử dụng cú pháp nguyên văn
[]
để khởi tạo mảng. eslint:no-array-constructor
4.2 Sử dụng Array#push, thay vì phép gán, để thêm các mục cho một mảng.
4.3 Sử dụng toán tử liệt kê
...
để sao nhanh một mảng.4.4 Để chuyển đổi một đối tượng khả duyệt thành một mảng, sử dụng toán tử liệt kê
...
thay vìArray.from
.4.5 Sử dụng
Array.from
để chuyển đổi một đối tượng giống-mảng thành một mảng.4.6 Sử dụng
Array.from
, thay vì toán tử liệt kê...
, để ánh xạ một đối tượng khả duyệt, vì nó không tạo ra một mảng trung gian.4.7 Sử dụng các lệnh
return
cho các hàm gọi lại dùng cho các phương thức của mảng. Được phép bỏ quareturn
nếu phần thân hàm chỉ gồm một câu lệnh trả về một biểu thức không có hiệu ứng phụ, theo quy tắc 8.2. eslint:array-callback-return
4.8 Sử dụng dấu ngắt dòng trước và sau các dấu đóng và mở ngoặc vuông nếu một mảng nằm trên nhiều dòng.
Trích xuất
5.1 Sử dụng trích xuất đối tượng khi truy cập và sử dụng nhiều thuộc tính của một đối tượng. eslint:
prefer-destructuring
Tại sao? Trích xuất giúp việc tạo các tham chiếu đến các thuộc tính trở nên dễ dàng hơn.
5.2 Hãy sử dụng trích xuất mảng. eslint:
prefer-destructuring
5.3 Sử dụng trích xuất đối tượng khi có nhiều giá trị trả về, thay vì trích xuất mảng.
Tại sao? Bạn có thể thêm các thuộc tính mới qua thời gian hay thay đổi thứ tự các thứ mà không lo làm hỏng các phép gọi trước đó.
Các Chuỗi
6.1 Sử dụng dấu lược cho các chuỗi. eslint:
quotes
6.2 Các chuỗi, dù khiến cho độ dài của dòng lớn hơn 100 ký tự, không nên được viết thành nhiều dòng sử dụng ghép chuỗi.
Tại sao? Các chuỗi bị chia nhỏ rất khó để làm việc cùng và khiến việc tìm kiếm trong mã nguồn trở nên khó hơn.
6.3 Khi xây dựng các chuỗi theo một chu trình, sử dụng mẫu chuỗi thay vì ghép chuỗi. eslint:
prefer-template
template-curly-spacing
Tại sao? Các mẫu chuỗi cho bạn một cú pháp súc tích, dễ đọc với các ngắt dòng và các tính năng ghép chuỗi phù hợp.
6.4 Không bao giờ sử dụng
eval()
cho một chuỗi, điều đó mở ra rất nhiều các lỗ hổng và rủi ro. eslint:no-eval
6.5 Không sử dụng các ký tự thoát trong một chuỗi khi không cần thiết. eslint:
no-useless-escape
Tại sao? Các dấu chéo ngược làm giảm tính khả đọc, vì thế chúng chỉ nên xuất hiện khi cần.
Các Hàm
7.1 Sử dụng biểu thức hàm hữu danh thay vì khai báo hàm. eslint:
func-style
Tại sao? Các khai báo hàm đều được kéo lên, đồng nghĩa với việc một hàm rất dễ có khả năng được sử dụng trước cả khi nó được định nghĩa trong tệp. Điều này làm giảm tính khả đọc và khả năng bảo trì. Nếu bạn thấy một hàm đủ lớn hoặc phức tạp đến mức ảnh hưởng đến việc đọc hiểu phần còn lại của tệp thì, có lẽ, nó nên được tách ra thành một mô-đun riêng! Đừng quên đặt tên cho biểu thức một cách rõ ràng, cho dù tên hàm có thể được suy ra từ tên biến chứa hàm đó (thường gặp ở các trình duyệt mới nhất hoặc các trình biên dịch như Babel). Điều này loại bỏ các nhận định liên quan đến ngăn xếp của một lỗi. (Cuộc thảo luận)
7.2 Đặt các biểu thức hàm gọi tức thời trong ngoặc. eslint:
wrap-iife
Tại sao? Một biểu thức hàm gọi tức thời mà một đơn vị riêng - đặt nó và dấu ngoặc dùng để gọi nó
()
trong ngoặc để biểu đạt nó một cách rõ ràng. Cũng cần biết là, trong cái thế giới mà mô-đun ngập tràn mọi nơi như bây giờ, bạn cũng chả mấy khi cần dùng đến biểu thức hàm gọi tức thời.7.3 Không bao giờ khai báo một hàm bên trong một khối không phải hàm (
if
,while
, v.v.). Thay vào đó, hãy gán hàm cho một biến. Các trình duyệt đều sẽ cho phép bạn làm điều đó, nhưng tiếc là, cách mà chúng diễn dịch là khác nhau. eslint:no-loop-func
7.4 Ghi chú: ECMA-262 định nghĩa một
khối
là tập hợp một hoặc một vài câu lệnh. Một khai báo hàm không phải là một câu lệnh.7.5 Không bao giờ đặt tên một tham số là
arguments
. Tham số này sẽ được ưu tiên hơn đối tượngarguments
được cung cấp cho mỗi phạm vi hàm.7.6 Không bao giờ sử dụng
arguments
, thay vào đó, hãy sử dụng cú pháp còn-lại...
. eslint:prefer-rest-params
Tại sao?
...
định rõ các đối số mà bạn muốn lấy. Thêm nữa, kết quả của còn-lại là một mảng đúng nghĩa, thay vì chỉ là giống-mảng nhưarguments
.7.7 Sử dụng tham số mặc định thay vì làm biến đổi các đối số truyền vào hàm.
7.8 Tránh gây ra hiệu ứng phụ với tham số mặc định.
Tại sao? Chúng khá là rối để có thể hình dung.
7.9 Luôn để các tham số mặc định ở sau cùng.
7.10 Không bao giờ sử dụng hàm tạo
Function
để tạo hàm. eslint:no-new-func
Tại sao? Tạo một hàm theo cách này cũng thực thi chuỗi giống như
eval()
vậy, thứ mà mở ra các lỗ hổng.7.11 Sử dụng các dấu cách giữa các bộ phận hàm. eslint:
space-before-function-paren
space-before-blocks
Tại sao? Sự đồng nhất vẫn cứ là tốt, và bạn không cần phải thêm hoặc bớt dấu cách khi không đặt tên hàm.
7.12 Không bao giờ làm biến đổi các tham số. eslint:
no-param-reassign
Tại sao? Việc can thiệp vào các đối tượng được truyền vào dưới dạng tham số có thể gây hiệu ứng phụ không mong muốn đối với biến tại tiến trình gọi.
7.13 Không bao giờ gán lại các tham số. eslint:
no-param-reassign
Tại sao? Việc gán lại các tham số có thể dẫn tới hành vi không mong muốn, đặc biệt là khi truy cập đối tượng
arguments
. Nó cũng có thể gây ra một số vấn đề về tối ưu hóa, nhất là trong V8.7.14 Ưu tiên sử dụng toán tử liệt kê
...
để gọi các hàm bất định. eslint:prefer-spread
Tại sao? Nó nhìn sáng sủa hơn, bạn không cần phải đặt ngữ cảnh, và bạn cũng đâu thể dễ dàng kết hợp
new
vớiapply
.7.15 Các hàm với các bộ phận hàm, hoặc các phép gọi, nằm trên nhiều dòng nên được căn đầu dòng như tất cả các danh sách nhiều dòng khác trong hướng dẫn này: với mỗi mục nằm trên một dòng riêng biệt, cùng với một dấu phẩy ngay sau mục cuối cùng. eslint:
function-paren-newline
Các Hàm mũi tên
8.1 Khi bạn phải sử dụng một hàm vô danh (như khi cần truyền một hàm gọi lại trên cùng dòng), sử dụng ký pháp hàm mũi tên. eslint:
prefer-arrow-callback
,arrow-spacing
Tại sao? Nó tạo ra một hàm thực thi trên ngữ cảnh của
this
, thường là thứ bạn cần, và nó rất súc tích.Khi nào thì không? Khi bạn có một hàm tương đối rắc rối, bạn cần phải chuyển lô-gíc của hàm đó sang biểu thức hàm hữu danh.
8.2 Nếu như phần thân hàm chỉ gồm một câu lệnh trả về một biểu thức mà không có hiệu ứng phụ, bỏ qua dấu ngoặc nhọn và sử dụng trả về ngầm định. Nếu không, giữ nguyên dấu ngoặc và sử dụng lệnh
return
. eslint:arrow-parens
,arrow-body-style
Tại sao? Cú pháp tiện lợi. Nó dễ đọc khi nhiều hàm nối chuỗi nhau.
8.3 Trong trường hợp biểu thức nằm trên nhiều dòng, nhóm nó trong ngoặc để dễ đọc hơn.
Tại sao? Nó cho thấy một cách rõ ràng điểm bắt đầu và kết thúc hàm.
8.4 Nếu hàm của bạn nhận một đối số và không sử dụng ngoặc nhọn, loại bỏ dấu ngoặc tròn. Nếu không, luôn luôn thêm ngoặc tròn trước và sau các đối số cho rõ ràng và nhất quán. Ghi chú: việc luôn sử dụng dấu ngoặc tròn được chấp nhận, khi đó, sử dụng tùy chọn “always” cho eslint. eslint:
arrow-parens
Tại sao? Nhìn bớt rối mắt.
8.5 Tránh gây dễ nhầm lẫn giữa cú pháp hàm mũi tên (
=>
) với các toán tử so sánh (<=
,>=
). eslint:no-confusing-arrow
8.6 Cách đặt vị trí của phần thân hàm mũi tên với trả về ngầm định. eslint:
implicit-arrow-linebreak
Các Lớp và các Hàm tạo
9.1 Luôn sử dụng
class
. Tránh việc can thiệp trực tiếp vàoprototype
.Tại sao? Cú pháp
class
súc tích, dễ hiểu và dễ hình dung.9.2 Sử dụng
extends
cho thừa kế.Tại sao? Nó là cách sẵn có để thừa kế nguyên mẫu mà không làm ảnh hưởng đến
instanceof
.9.3 Các phương thức, mỗi khi có thể, hãy trả về
this
để tiện cho việc nối chuỗi phương thức.9.4 Có thể viết phương thức
toString()
tùy ý, chỉ cần đảm bản nó hoạt động hoàn hảo và không gây ra các hiệu ứng phụ.9.5 Các lớp có một hàm tạo mặc định nếu không được chỉ định. Một hàm tạo rỗng, hoặc chỉ trỏ đến lớp cha, là không cần thiết. eslint:
no-useless-constructor
9.6 Tránh trùng lặp các thành viên của một lớp. eslint:
no-dupe-class-members
Tại sao? Với các khai báo thành viên bị lặp, khai báo cuối được tự động ưu tiên - việc có sự trùng lặp gần như chắc chắn là một lỗi.
Các Mô-đun
10.1 Luôn sử dụng mô-đun (
import
/export
) thay vì một hệ thống mô-đun phi chuẩn. Bạn luôn có thể dịch mã sang hệ thống mô-đun mà bạn thích.Tại sao? Mô-đun là tương lai, hãy cùng sử dụng tương lai ngay lúc này.
10.2 Không sử dụng ký tự đại diện để nhập.
Tại sao? Điều này đảm bảo bạn chỉ xuất mặc định một giá trị.
10.3 Và không xuất trực tiếp từ một lệnh nhập.
Tại sao? Mặc dù cấu trúc một dòng là súc tích, việc nhập một cách rõ ràng và xuất một cách rõ ràng làm cho mọi thứ nhất quán.
10.4 Chỉ nhập từ một đường dẫn ở chung một chỗ. eslint:
no-duplicate-imports
Tại sao? Có nhiều dòng nhập từ cùng một đường dẫn khiến mã nguồn trở nên khó bảo trì hơn.
10.5 Không xuất các ràng buộc có thể bị biến đổi. eslint:
import/no-mutable-exports
Tại sao? Sự biến đổi, nói chung, nên được tránh, nhưng đặc biệt là đối với trường hợp xuất các giá trị có thể bị biến đổi. Trong khi kỹ thuật này có thể là cần thiết trong một số trường hợp đặc biệt, nhìn chung, chỉ nên xuất các giá trị là hằng.
10.6 Trong các mô-đun chỉ có một địa chỉ xuất, ưu tiên xuất mặc định thay vì xuất hữu danh. eslint:
import/prefer-default-export
Tại sao? Nhằm khuyến khích các tệp chỉ xuất một giá trị, giúp mã nguồn dễ đọc và dễ bảo trì.
10.7 Đặt tất cả các lệnh
import
trên cùng. eslint:import/first
Tại sao? Vì các lệnh
import
được kéo lên, việc đặt tất cả chúng ở trên cùng nhằm ngăn chặn các hành vi không đáng có.10.8 Các lệnh nhập nhiều dòng nên được căn đầu dòng giống như các mảng hay đối tượng nguyên văn nhiều dòng.
Tại sao? Các đấu ngoặc nhọn đều có cùng các quy tắc căn đầu dòng như tất cả mọi khối ngoặc nhọn trong bản định hướng này, cùng với như dấu phẩy ở cuối.
10.9 Không cho phép cú pháp bộ tải Webpack trong các lệnh nhập mô-đun. eslint:
import/no-webpack-loader-syntax
Tại sao? Vì sử dụng cú pháp Webpack trong các lệnh nhập gom mã thành một bộ tổng hợp mô-đun. Ưu tiên sử dụng cú pháp bộ tải trong
webpack.config.js
.
Các Đối tượng duyệt và các Hàm sinh trị
11.1 Không sử dụng các đối tượng duyệt. Ưu tiên sử dụng các hàm bậc cao hơn của JavaScript thay vì các vòng lặp như
for-in
hayfor-of
. eslint:no-iterator
no-restricted-syntax
Tại sao? Điều này đảm bảo việc thực hiện quy tắc bất biến. Làm việc với các hàm thuần mà trả về các giá trị sẽ dễ tưởng tượng hơn so với các hiệu ứng phụ.
Sử dụng
map()
/every()
/filter()
/find()
/findIndex()
/reduce()
/some()
/ ... để duyệt qua một mảng, vàObject.keys()
/Object.values()
/Object.entries()
để tạo một mảng để bạn có thể duyệt qua một đối tượng.11.2 Không sử dụng các hàm sinh trị
function*
vào thời điểm này.Tại sao? Nó không thể được dịch mã sang ES5 một cách hoàn hảo.
11.3 Nếu bạn bắt buộc phải dùng các hàm sinh trị, hoặc bạn bỏ qua khuyến nghị của chúng tôi, hãy đảm bảo rằng bạn sử dụng dấu cách giữa các bộ phận hàm một cách hợp lý. eslint:
generator-star-spacing
Tại sao?
function
và*
là tạo thành một từ khóa riêng -*
không phải là từ khóa điều chỉnh chofunction
,function*
là một cấu tạo riêng biệt, khác vớifunction
.
Các Thuộc tính
12.1 Sử dụng ký pháp chấm
.
để truy cập các thuộc tính. eslint:dot-notation
12.2 Sử dụng ký pháp ngoặc
[]
để truy cập thuộc tính với một biến.12.3 Sử dụng toán tử lũy thừa
**
để tính các lũy thừa. eslint:no-restricted-properties
.
Các Biến
13.1 Luôn sử dụng
const
hoặclet
để khai báo biến. Không làm như vậy sẽ dẫn đến các biến toàn cục. Chúng ta muốn tránh việc làm ô nhiễm không gian tên toàn cục. Đội trưởng Hành tinh đã cảnh báo chúng ta. eslint:no-undef
prefer-const
13.2 Sử dụng một
const
hoặclet
khai báo cho mỗi biến hoặc phép gán. eslint:one-var
Tại sao? Khai báo theo cách này giúp dễ thêm các khai báo mới, và bạn chẳng phải nghĩ về việc phải dùng
;
hay,
. Bạn còn có thể bước qua mỗi khai báo trong trình gỡ lỗi, thay vì nhảy qua toàn bộ chúng trong một bước.13.3 Nhóm tất cả các
const
và rồi nhóm tất cả cáclet
.Tại sao? Điều này hữu ích khi, sau đó, bạn sẽ cần gán lại một biến dựa trên các biến đã gán trước đó.
13.4 Chỉ gán biến khi cần, nhưng nhớ đặt chúng ở một nơi hợp lý.
Tại sao?
let
vàconst
thuộc phạm vi khối, không phải phạm vi hàm.13.5 Đừng nối chuỗi các phép gán. eslint:
no-multi-assign
Tại sao? Việc nối chuỗi các phép gán tạo ra các biến toàn cục ngầm định.
13.6 Tránh việc sử dụng các phép tăng và giảm một ngôi (
++
,--
). eslintno-plusplus
Tại sao? Theo như tài liệu của eslint, các phép tăng hoặc giảm một ngôi phụ thuộc vào Quy tắc thêm dấu chấm phẩy tự động và có thể gây ra các lỗi câm trong việc tăng hoặc giảm các giá trị trong một ứng dụng. Sự diễn đạt cũng trở nên rõ ràng hơn khi bạn biến đổi các giá trị với các lệnh, như
num += 1
, thay vìnum++
haynum ++
. Việc không cho phép các lệnh tăng hoặc giảm một ngôi cũng giúp bạn tránh được các sự tiền tăng/tiền giảm các giá trị một cách không chủ ý, điều có thể cũng gây ra những hành vi không mong muốn cho chương trình của bạn.13.7 Tránh các dấu ngắt dòng trước và sau
=
trong một phép gán. Nếu phép gán của bạn vi phạmmax-len
, hãy đặt giá trị trong ngoặc tròn. eslintoperator-linebreak
.Tại sao? Các dấu ngắt dòng quanh
=
có thể làm mờ nhạt giá trị trong phép gán.13.8 Không cho phép các biến không được sử dụng. eslint:
no-unused-vars
Tại sao? Các biến được khai báo nhưng không được sử dụng ở khắp mọi nơi trong mã gần như chắc chắn là một lỗi do sự cải tiến mã nguồn chưa hoàn thiện. Những biến như vậy chiếm chỗ trong mã và có thể gây ra sự khó hiểu cho người đọc.
Sự kéo lên
14.1 Các khai báo bằng
var
được kéo lên đầu của phạm vi hàm gần nhất, còn phép gán thì không. Các khai báo bằngconst
vàlet
thì mang trên mình một đặc tính khác là Giai đoạn chết. Điều này là quan trọng để biết tại saotypeof
không còn an toàn.14.2 Các biểu thức hàm vô danh sẽ được kéo tên biến lên, nhưng không được kéo phép gán hàm.
14.3 Biểu thức hàm hữu danh sẽ được kéo tên biến lên, nhưng không được kéo tên hàm và thân hàm.
14.4 Khai báo hàm được kéo cả tên và thân hàm lên.
Để tìm hiểu thêm, tham khảo bài viết JavaScript Scoping & Hoisting bởi Ben Cherry.
Các Toán tử So sánh và Sự bằng nhau
15.1 Sử dụng
===
và!==
thay vì==
và!=
. eslint:eqeqeq
15.2 Các câu lệnh điều kiện như lệnh
if
xét biểu thức của chúng bằng cách ép kiểu bằng một phương thức ảoToBoolean
và đều tuân theo những quy tắc đơn giản sau:Các đối tượng tương đương với true
Undefined tương đương với false
Null tương đương với false
Các boolean tương đương với giá trị của boolean
Các số tương đương với false nếu là +0, -0, hoặc NaN, còn không sẽ là true
Các chuỗi tương đương vớivfalse nếu là một chuỗi rỗng
''
, còn không sẽ là true
15.3 Sử dụng dạng rút gọn cho các boolean, nhưng dùng dạng so sánh cụ thể đối với chuỗi và số.
15.4 Để biết thêm chi tiết, xem bài viết Truth Equality and JavaScript bởi Angus Croll.
15.5 Sử dụng các dấu ngoặc cho các khối của mệnh đề
case
vàdefault
nếu nó có chứa các khai báo (nhưlet
,const
,function
, vàclass
). eslint:no-case-declarations
Tại sao? Các khai báo tồn tại trong cả khối
switch
nhưng chỉ được khởi tạo khi được gán, mà nó chỉ xảy ra khicase
của nó xảy ra. Điều này gây ra các lỗi khi mà nhiều mệnh đềcase
muốn định nghĩa cùng một thứ.15.6 Các toán tử ba ngôi không nên được đặt trong ngoặc và thường được viết trên một dòng riêng. eslint:
no-nested-ternary
15.7 Tránh các câu lệnh ba ngôi không đáng có. eslint:
no-unneeded-ternary
15.8 Khi kết hợp các toán tử, nhớ đóng chúng trong ngoặc. Ngoại lệ duy nhất là các toán tử tiêu chuẩn (
+
,-
,*
, &/
) vì chúng có thứ tự ưu tiên mà ai ai cũng hiểu. eslint:no-mixed-operators
Tại sao? Điều này cả thiện tính khả đọc và làm rõ ý định của nhà phát triển.
Các Khối
16.1 Sử dụng các dấu ngoặc cho các khối nhiều dòng. eslint:
nonblock-statement-body-position
16.2 Nếu bạn đang sử dụng các khối nhiều dòng với
if
vàelse
, đặtelse
trên cùng dòng với dấu đóng ngoặc của khốiif
. eslint:brace-style
16.3 Nếu một khối
if
luôn thực hiện lệnhreturn
, những khốielse
tiếp theo là không cần thiết. Một lệnhreturn
trong một khốielse if
theo sau một khốiif
mà có chứareturn
có thể được tách thành nhiều khốiif
. eslint:no-else-return
Các Câu lệnh Điều khiển
17.1 Nếu trong trường hợp lệnh điều khiển (
if
,while
, v.v.) của bạn trở lên quá dài và vượt quá giới hạn độ dài dòng, mỗi (nhóm) điều kiện có thể được đặt ở một dòng mới. Toán tử lô-gíc nên được đặt ở đầu dòng.Tại sao? Việc đặt các toán tử ở đầu dòng giúp các toán tử được căn đều và tuân theo cùng một mô hình với việc nối chuỗi phương thức. Điều này cũng cải thiện tính khả đọc vì khiến cho việc theo dõi một lô-gíc phức tạp trở nên đơn giản hơn.
17.2 Không sử dụng toán tử lựa chọn thay cho các câu lệnh điều khiển.
Các Chú thích
18.1 Sử dụng
/** ... */
cho các chú thích nhiều dòng.18.2 Sử dụng
//
cho các chú thích một dòng. Đặt các chú thích một dòng ở một dòng riêng, bên trên chủ đề của chú thích. Để một dòng trống trước chú thích trừ khi chú thích là dòng đầu tiên của một khối.18.3 Bắt đầu tất cả các chú thích bằng một dấu cách để dễ đọc hơn. eslint:
spaced-comment
18.4 Thêm
FIXME
hoặcTODO
vào đầu chú thích giúp các nhà phát triển dễ dàng biết được rằng bạn đang chỉ ra một vấn đề cần được xem lại, hoặc bạn đang đề xuất cách giải quyết cho vấn đề nên mà được áp dụng. Các hành động có thể nhưFIXME: -- cần xem xét về thứ này
hoặcTODO: -- cần áp dụng
.18.5 Sử dụng
// FIXME:
để chú giải các vấn đề.18.6 Sử dụng
// TODO:
để chú giải các cách giải quyết cho các vấn đề.
Khoảng trắng
19.1 Sử dụng các tab ngắn (dấu cách) đặt về 2 dấu cách. eslint:
indent
19.2 Đặt 1 cách trước dấu mở ngoặc. eslint:
space-before-blocks
19.3 Đặt 1 dấu cách trước dấu mở ngoặc tròn của các lệnh điều khiển (
if
,while
, v.v.). Không đặt dấu cách giữa danh sách đối số và tên hàm trong các phép gọi và khai báo hàm. eslint:keyword-spacing
19.4 Đặt dấu cách trước và sau các toán tử. eslint:
space-infix-ops
19.6 Căn đầu dòng khi tạo các chuỗi phương thức (nhiều hơn 2 chuỗi phương thức). Đặt dấu chấm ở đầu, để nhấn mạnh dòng này là một phép gọi phương thức, không phải là một câu lệnh mới. eslint:
newline-per-chained-call
no-whitespace-before-property
19.7 Để một dòng trống sau mỗi khối và trước câu lệnh tiếp theo.
19.8 Không kê các khối với các dòng trống. eslint:
padded-blocks
19.9 Do not use multiple blank lines to pad your code. eslint:
no-multiple-empty-lines
``` javascript // không tốt class Person { constructor(fullName, email, birthday) { this.fullName = fullName;
19.10 Không thêm các dấu cách trong dấu ngoặc tròn. eslint:
space-in-parens
19.11 Không thêm các dấu cách trong các dấu ngoặc vuông. eslint:
array-bracket-spacing
19.12 Thêm các dấu cách giữa các dấu ngoặc nhọn. eslint:
object-curly-spacing
19.13 Tránh các dòng mã có nhiều hơn 100 ký tự (kể cả khoảng trắng). Lưu ý: theo như trên đây, các chuỗi được loại trừ bởi quy tắc này, và bạn không nên chia chúng ra. eslint:
max-len
Tại sao? Điều này đảm bảo tính khả đọc và khả năng bảo trì.
19.14 Đảm bảo sự nhất quán về dấu cách sau dấu mở ngoặc và trước ký tự đầu tiên sau nó trên cùng một dòng. Quy tắc này cũng yêu cầu sự nhất quán về dấu cách trước dấu đóng ngoặc và sau ký tự cuối cùng trước nó trên cùng một dòng. eslint:
block-spacing
19.15 Không sử dụng dấu cách trước dấu phẩy và phải sử dụng dấu cách sau dấu phẩy. eslint:
comma-spacing
19.16 Không đặt dấu cách bên trong dấu ngoặc của thuộc tính được tính. eslint:
computed-property-spacing
19.17 Tránh sử dụng dấu cách giữa các hàm và phép gọi chúng. eslint:
func-call-spacing
19.18 Đặt dấu cách giữa các tên và giá trị của các thuộc tính nguyên văn. eslint:
key-spacing
19.19 Tránh các dấu cách ở cuối các dòng. eslint:
no-trailing-spaces
19.20 Tránh để nhiều dòng trống liên tiếp và chỉ cho một dòng trống ở cuối tệp. eslint:
no-multiple-empty-lines
``` javascript // không tốt var x = 1;
Các Dấu phẩy
20.1 Các dấu phẩy ở đầu: Đừng! eslint:
comma-style
20.2 Thêm một dấu phẩy ở cuối: Đúng đó! eslint:
comma-dangle
Tại sao? Điều này làm cho các so sánh git gọn gàng hơn. Ngoài ra, các trình dịch mã như Babel sẽ xóa các dấu phẩy ở cuối trong mã được dịch, có nghĩa là bạn không cần lo lắng về vấn đề của dấu phẩy ở cuối trên các trình duyệt cũ.
Các Dấu chấm phẩy
21.1 Dĩ nhiên. eslint:
semi
Tại sao? Khi JavaScript gặp một dấu ngắt dòng mà không có dấu chấm phẩy, nó sử dụng một bộ quy tắc gọi là Quy tắc thêm dấu chấm phẩy tự động để xác định xem dấu ngắt dòng có phải là kết thúc của một câu lệnh hay không, và (như cái tên gợi ý) đặt một dấu chấn phẩy vào mã của bạn, trước dấu ngắt dòng, nếu nó cho rằng nên làm vậy. Quy tắc thêm dấu chấm phẩy tự động có một vài hành vi lập dị, và mã của bạn sẽ hỏng nếu JavaScript hiểu sai dấu ngắt dòng của bạn. Những quy tắc này ngày càng trở nên phức tạp khi các tính năng mới được bổ sung vào JavaScript. Việc kết thúc các câu lệnh một cách rõ ràng và thiết lập trình phân tích mã của bạn bắt các lỗi thiếu dấu phẩy sẽ giúp bạn tránh được các vấn đề.
Sự ép kiểu
22.1 Thực hiện ép kiểu ở đầu mỗi câu lệnh.
22.2 Đối với các chuỗi: eslint:
no-new-wrappers
22.3 Đối với các số: Sử dụng
Number
để ép kiểu vàparseInt
luôn phải được dùng với một cơ số. eslint:radix
no-new-wrappers
22.4 Nếu, vì bất cứ lý do gì, bạn đang làm một điều gì đó thật điên và bạn gặp nghẽn cổ chai do
parseInt
, và bạn cần sử dụng phép dịch chuyển bit vì các lý do hiệu suất, nhớ để lại một chú thích để giải thích về thứ bạn đang làm và tại sao bạn làm vậy.22.5 Lưu ý: Cẩn thận khi sử dụng các phép dịch chuyển bit. Các số được biểu diễn dưới dạng các giá trị 64-bit, nhưng các phép dịch chuyển bit luôn trả về một số nguyên 32-bit (nguồn). Phép dịch chuyển bit cũng có thể dẫn đến các hành vi không mong đợi đối với các giá trị lớn hơn 32 bit. Cuộc thảo luận. Số nguyên có dấu 32-bit lớn nhất là 2,147,483,647:
22.6 Đối với các boolean: eslint:
no-new-wrappers
Các Quy ước Đặt tên
23.1 Tránh sử dụng các tên chỉ có một chữ cái. Hãy đặt những cái tên thật ý nghĩa. eslint:
id-length
23.2 Sử dụng camelCase khi đặt tên các đối tượng, các hàm và các thực thể. eslint:
camelcase
23.3 Sử dụng PascalCase chỉ khi đặt tên các hàm tạo hay các lớp. eslint:
new-cap
23.4 Không sử dụng các dấu gạch dưới ở đằng trước hoặc đằng sau. eslint:
no-underscore-dangle
Tại sao? JavaScript không có khái niệm về tính riêng tư khi nói đến các thuộc tính hay các phương thức. Tuy rằng một dấu gạch dưới đặt ở đằng trước là một quy ước chung mang nghĩa “riêng tư”, thực tế, các thuộc tính trên đều hoàn toàn công khai, và vì vậy, là các thành phần trong API của bạn. Quy ước này có thể khiến các nhà phát triển nghĩ, một cách sai lầm, rằng một sự thay đổi chẳng làm hỏng điều gì, hoặc không cần thiết phải kiểm thử. tl;dr: nếu bạn muốn thứ gì đó thật “riêng tư”, sự tồn tại của nó phải được giấu đi.
23.5 Đừng lưu các tham chiếu đến
this
. Hãy sử dụng hàm mũi tên hoặc Function#bind.23.6 Phần tên của một tên tệp nên giống với địa chỉ xuất mặc định của tệp đó.
23.7 Sử dụng camelCase khi xuất mặc định một hàm. Tên tệp nên trùng với tên hàm.
23.8 Sử dụng PascalCase khi xuất mặc định một hàm tạo / lớp / đối tượng độc nhật / một thư viện các hàm / đối tượng trần.
23.9 Các từ viết tắt nên được viết hoa hoặc viết thường toàn bộ.
Tại sao? Các tên dùng để đọc, không phải để giải thích thuật toán.
23.10 Bạn có chọn viết hoa một hằng chỉ khi hằng đó (1) được xuất, và (2) một lập trình viên có thể tin tưởng rằng nó (và các thuộc tính của nó) là bất biến.
Tại sao? Đây là một công cụ khác để hỗ trợ chúng ta trong các hoàn cảnh mà một lập trình viên có thể không chắc chắn là một biến có bị thay đổi hay chưa. UPPERCASE_VARIABLES đang cho lập trình viên đó biết là biến này (và thuộc tính của nó) không có thay đổi gì hết.
Thế còn các
const
? - Điều này là không cần thiết, vì việc viết hoa không nên được sử dụng cho các hằng ở trong cùng một tệp. Nó chỉ nên dùng cho các hằng được xuất.Thế còn một đối tượng được xuất thì sao? - Chỉ viết hoa ở hàng cao nhất của đối tượng xuất (kiểu như:
EXPORTED_OBJECT.key
) và đảm bảo rằng những thuộc tính của nó không thay đổi.
Các Hàm truy cập
24.1 Các hàm truy cập cho các thuộc tình là không bắt buộc.
24.2 Không sử dụng hàm đọc/hàm ghi của JavaScript vì chúng gây ra các hiệu ứng phụ không mong muốn và khó để kiểm thử, bảo trì, và hình dung. Thay vào đó, nếu bạn muốn tạo hàm truy cập, sử dụng
getVal()
vàsetVal('hello')
.24.3 Nếu thuộc tính/phương thức là một
boolean
, dùngisVal()
hoặchasVal()
.24.4 Có thể dùng các hàm
get()
vàset()
, nhưng nhớ là phải nhất quán.
Các Sự kiện
25.1 Khi gắn các trọng tải dữ liệu cho các sự kiện (dù là các sự kiện DOM hay thứ gì đó tư hữu hơn như các sự kiện trong Backbone), hãy truyền vào một đối tượng nguyên văn (hay còn gọi là "giá trị băm") thay vì giá trị gốc. Điều này cho phép những người đóng góp sau này có thể thêm dữ liệu vào trọng tải mà không cần phải tìm và cập nhật mỗi hàm xử lý cho sự kiện. Ví dụ, thay vì:
hãy dùng:
Tính tương thích của ECMAScript 5
27.1 Tham khảo bảng tính tương thích ES5 của Kangax.
Lối viết ECMAScript 6+ (ES 2015+)
28.1 Đây là một bộ sưu tập các liên kết tới các tính năng khác nhau của ES6+.
Các Hàm mũi tên
Các Lớp
Cú pháp Định nghĩa Phương thức Rút gọn
Cú pháp Định nghĩa Thuộc tính Rút gọn
Các Tên Được tính của Thuộc tính
Các Mẫu chuỗi
Trích xuất
Các Tham số Mặc định
Còn-lại
Liệt kê Mảng
Let và Const
Toán tử Lũy thừa
Các Đối tượng duyệt và các Hàm sinh trị
Các Mô-đun
28.2 Không sử dụng các đề xuất TC39 mà chưa đến giai đoạn 3.
Tại sao? Chúng chưa được hoàn thiện, và chúng có thể thay đổi bất cứ lúc nào hoặc bị rút lại hoàn toàn. Chúng ta muốn sử dụng JavaScript, mà các đề xuất thì chưa phải là JavaScript.
Thư viện Tiêu Chuẩn
Thư viện tiêu chuẩn chứa các hàm tiện ích không hoạt động đúng lắm nhưng vẫn tồn tại vì các lý do cũ.
29.1 Sử dụng
Number.isNaN
thay vì hàm toàn cụcisNaN
. eslint:no-restricted-globals
Tại sao? Hàm toàn cục
isNaN
ép các giá trị không phải số thành số và trả về true cho tất cả những gì mà bị ép thành NaN. Nếu đây là hành vi mong muốn, hãy khiến nó được biểu đạt rõ ràng.29.2 Sử dụng
Number.isFinite
thay vì hàm toàn cụcisFinite
. eslint:no-restricted-globals
Tại sao? Hàm toàn cục
isFinite
ép các giá trị không phải số thành số và trả về true cho tất cả những gì bị ép thành một số mà không phải là vô hạn. Nếu đây là hành vi mong muốn, hãy khiến nó được biểu đạt rõ ràng.
Sự kiểm thử
30.1 Có chứ.
30.2 Không, nhưng nghiêm túc này:
Dù bạn dùng nền tảng kiểm thử nào thì bạn cũng nên viết các kiểm thử!
Cố gắng viết thật nhiều các hàm thuần, nhỏ và giảm thiểu số các sự biến đổi.
Cẩn thận với các giả lập mô-đun và đối tượng - chúng có thể khiến các chương trình kiểm thử của bạn dễ vỡ.
100% độ bao phủ kiểm thử là một mục tiêu tốt để phấn đấu, dù không phải lúc nào cũng khả thi.
Mỗi khi bạn sửa một lỗi, viết một kiểm thử hồi quy. Một lỗi được sửa nhưng không được viết kiểm thử lại gần như chắc chắn sẽ lại hỏng trong tương lai.
Danh mục các Thuật ngữ
Dưới đây là danh mục các từ tiếng Anh tương ứng của các thuật ngữ, và/hoặc các từ, cụm từ mà thông thường không được dịch, như: "style guide", "object", "polyfill", v.v. Các từ, cụm từ được dịch có thể chỉ đúng trong ngữ cảnh là bản dịch này.
Nếu bạn cảm thấy một thuật ngữ có vẻ được dịch chưa hợp lý, hoặc bạn cần sự giải thích về một thuật ngữ, bạn có thể mở một Vấn đề để thảo luận.
Nếu bạn biết một từ/cụm từ tiếng Việt thích hợp hơn cho một thuật ngữ, và nếu bạn sẵn lòng, bạn có thể mở một Đề nghị kéo cho một sửa đổi.
( nguồn : @Airbnb React/JSX Style Guide )
Last updated