Giới thiệu cuốn Maintainable Javascript 2
Bài đăng này đã không được cập nhật trong 9 năm
1. Comments
1.1. Comment 1 dòng
// Ví dụ tốt
if (condition) {
// if you made it here, then all security checks passed
allowed();
}
// Không tốt: Không có dòng trống trước comment
if (condition) {
// if you made it here, then all security checks passed
allowed();
}
// Không tốt: Sai lề
if (condition) {
// if you made it here, then all security checks passed
allowed();
}
// Ví dụ tốt
var result = something + somethingElse; // somethingElse will never be null
// Không tốt: Không đủ khoảng trống giữa code và comment
var result = something + somethingElse;// somethingElse will never be null
// Tốt
// if (condition) {
// doSomething();
// thenDoSomethingElse();
// }
// Không tốt: Đoạn này nên dùng comment nhiều dòng
// This next piece of code is quite difficult, so let me explain.
// What you want to do is determine whether the condition is true
// and only then allow the user in. The condition is calculated
// from several different functions and may change during the
// lifetime of the session.
if (condition) {
// if you made it here, then all security checks passed
allowed();
}
1.2. Comment nhiều dòng
// Ví dụ tốt
if (condition) {
/*
* if you made it here,
* then all security checks passed
*/
allowed();
}
// Không tốt: Không có dòng trống trước comment
if (condition) {
/*
* if you made it here,
* then all security checks passed
*/
allowed();
}
// Không tốt: Thiếu khoảng trống sau dấu *
if (condition) {
/*
*if you made it here,
*then all security checks passed
*/
allowed();
}
// Không tốt: Sai lề
if (condition) {
/*
* if you made it here,
* then all security checks passed
*/
allowed();
}
// Không tốt: Không dùng comment nhiều dòng cho comment đuôi
var result = something + somethingElse; /*somethingElse will never be null*/
1.3 Sử dụng comment
1.3.1 Sử dụng comment để giải thích rõ nghĩa code
// Không tốt
// Khởi tạo count
var count = 10;
//Tốt
// Thay đổi giá trị này sẽ dẫn đến những thay đổi nghiêm trọng
var count = 10;
1.3.1.1 Giải thích các đoạn code khó hiểu
// Ví dụ tốt
if (mode) {
/*
* In mode 2 (prototype to prototype and object to object), we recurse
* once to do the proto to proto mix. The object to object mix will be
* handled later on.
*/
if (mode === 2) {
Y.mix(receiver.prototype, supplier.prototype, overwrite,
whitelist, 0, merge);
}
/*
* Depending on which mode is specified, we may be copying from or to
* the prototypes of the supplier and receiver.
*/
from = mode === 1 || mode === 3 ? supplier.prototype : supplier;
to = mode === 1 || mode === 4 ? receiver.prototype : receiver;
/*
* If either the supplier or receiver doesn't actually have a
* prototype property, then we could end up with an undefined from
* or to. If that happens, we abort and return the receiver.
*/
if (!from || !to) {
return receiver;
}
} else {
from = supplier;
to = receiver;
}
1.3.1.2 Các đoạn code theo chủ ý của tác giả giống như là có lỗi
while (element &&(element = element[axis])) { // NOTE: assignment
if ( (all || element[TAG_NAME]) && (!fn || fn(element)) ) {
return element;
}
}
1.3.1.3 Hack Browser-Specific
var ret = false;
if ( !needle || !element || !needle[NODE_TYPE] || !element[NODE_TYPE]) {
ret = false;
} else if (element[CONTAINS]) {
// IE & SAF contains fail if needle not an ELEMENT_NODE
if (Y.UA.opera || needle[NODE_TYPE] === 1) {
ret = element[CONTAINS](needle);
} else {
ret = Y_DOM._bruteContains(element, needle);
}
} else if (element[COMPARE_DOCUMENT_POSITION]) { // gecko
if (element === needle || !!(element[COMPARE_DOCUMENT_POSITION](needle) & 16)) {
ret = true;
}
}
return ret;
1.3.1.3 Documentation comment
/**
Returns a new object containing all of the properties of all the supplied
objects. The properties from later objects will overwrite those in earlier
objects.
Passing in a single object will create a shallow copy of it. For a deep copy,
use `clone()`.
@method merge
@param {Object} objects* One or more objects to merge.
@return {Object} A new merged object.
**/
Y.merge = function () {
var args = arguments,
i = 0,
len = args.length,
result = {};
for (; i < len; ++i) {
Y.mix(result, args[i], true);
}
return result;
};
2. Các câu lệnh và diễn đạt
2.1. Các khối lệnh với cặp dấu ngoặc {}
2.1.1. Cặp dấu ngoặc {} có thể được dùng với tất cả các khối lệnh if, for, while, do…while, try…catch…finally
// Không tốt dù đúng ngữ pháp JavaScript
if(condition)
doSomething();
// Không tốt dù đúng ngữ pháp JavaScript
if(condition) doSomething();
// Ví dụ tốt
if (condition) {
doSomething();
}
// Không tốt dù đúng ngữ pháp JavaScript
if (condition) { doSomething(); }
2.1.2. Dùng cặp dấu ngoặc cũng giúp phát hiện lỗi dễ hơn và làm rõ ý định viết của người code.
Ví dụ
if (condition)
doSomething();
doSomethingElse();
Nêú dùng cặp dấu ngoặc {} sẽ phát hiện lỗi dễ hơn
if (condition) {
doSomething();
}
doSomethingElse();
}
Hoặc
if (condition) {
doSomething();
doSomethingElse();
}
2.1.3. Căn lề cặp dấu ngoặc
Có 2 cách căn lề cặp dấu ngoặc phổ biến a, Kế thừa từ Java
if (condition) {
doSomething();
} else {
doSomethingElse();
}
b, Theo kiểu của C#
if (condition)
{
doSomething();
}
else
{
doSomethingElse();
}
2.1.4. Khoảng trắng với cặp dấu ngoặc
2.1.4.1 Không có khoảng trắng giữa tên lệnh, dấu ngoặc đơn mở và dấu ngoặc nhọn mở
if(condition){
doSomething();
}
2.1.4.2 Có khoảng trắng giữa tên lệnh, dấu ngoặc đơn mở và dấu ngoặc nhọn mở
if (condition) {
doSomething();
}
2.1.4.3 Loại 2 thêm vào các khoảng trắng sau dấu ngoặc đơn mở và trước dấu ngoặc đơn đóng
if ( condition ) {
doSomething();
}
Tác giả thích loại 2 vì là sự cân bằng giữa loại 1 và 3.
2.2 Câu lệnh switch
2.2.1 Lề
2.2.1.1 Cách dùng phổ biến
switch(condition) {
case "first":
// code
break;
case "second":
// code
break;
case "third":
// code
break;
default:
// code
}
2.2.1.2 Crockford’s Code Conventions và Dojo Style Guide
switch(condition) {
case "first":
// code
break;
case "second":
// code
break;
case "third":
// code
break;
default:
// code
}
2.2.2 Nhảy qua Falling Through
switch(condition) {
// obvious fall through
case "first":
case "second":
// code
break;
case "third":
// code
/*falls through*/
default:
// code
}
2.2.3 default
2.2.3.1 Có default dù nó không làm gì
switch(condition) {
case "first":
// code
break;
case "second":
// code
break;
default:
// do nothing
}
2.2.3.2 Không viết default khi nó không làm gì
Khi default không làm gì, không viết nó mà chỉ viết comment //no default. Tác giả khuyến khích dùng cách này vì nó chỉ rõ chủ ý của tác giả là không có default và tiết kiệm bộ nhớ vì không cần dùng thêm cấu trúc không cần thiết.
switch(condition) {
case "first":
// code
break;
case "second":
// code
break;
// no default
}
2.3. Câu lệnh with
var book = {
title: "Maintainable JavaScript",
author: "Nicholas C. Zakas"
};
var message = "The book is ";
with (book) {
message += title;
message += " by " + author;
}
2.4 Vòng lặp for
2.4.1 break
var values = [ 1, 2, 3, 4, 5, 6, 7 ],
i, len;
for (i=0, len=values.length; i < len; i++) {
if (i == 2) {
break; // no more iterations
}
process(values[i]);
}
2.4.2 continue
var values = [ 1, 2, 3, 4, 5, 6, 7 ],
i, len;
for (i=0, len=values.length; i < len; i++) {
if (i == 2) {
continue; // skip just this iteration
}
process(values[i]);
}
Crockford’s Code Conventions không cho phép dùng continue vì nó có thể được thay thế sử dụng điều kiện và trở nên dễ hiểu, ít khả năng lỗi hơn. Ví dụ trên có thể viết bằng cách khác là:
var values = [ 1, 2, 3, 4, 5, 6, 7 ],
i, len;
for (i=0, len=values.length; i < len; i++) {
if (i != 2) {
process(values[i]);
}
}
. Tác giả khuyến khích tránh continue khi có thể tránh nhưng không loại bỏ nó hoàn toàn.
2.5 Vòng lặp for-in
2.5.1 hasOwnProperty()
Crockford’s Code Conventions yêu cầu và tác giả khuyến khích dùng hasOwnProperty() check để lọc vòng lặp for-in chỉ cho các thuộc tính instance vì for-in trả về cả các thuộc tính instance của object và các thuộc tính kế thừa từ prototype.
var prop;
for (prop in object) {
if (object.hasOwnProperty(prop)) {
console.log("Property name is " + prop);
console.log("Property value is " + object[prop]);
}
}
Khi muốn dùng với prototype chain, bạn nên dùng comment.
var prop;
for (prop in object) { // include prototype properties
console.log("Property name is " + prop);
console.log("Property value is " + object[prop]);
}
2.5.2 Dùng for-in với các đối tượng, Không dùng với mảng
// Không tốt
var values = [ 1, 2, 3, 4, 5, 6, 7],
i;
for (i in values) {
process(items[i]);
}
To be continued...
All rights reserved