作為一個(gè)編程4年的的前端工程師,一路走來踩過許多坑。希望我的經(jīng)驗(yàn)?zāi)茏屇闵俨刃┛樱诰幊痰穆飞献叩母樞?/p>
1. 禁用var聲明
只使用const或let聲明變量。并且首選const,當(dāng)一個(gè)變量需要重新賦值時(shí),才使用let。并且在創(chuàng)建變量時(shí)就應(yīng)該給變量賦值。
原因:
-
- var缺乏作用域的限制,很容易導(dǎo)致全局作用域污染,引發(fā)“命名沖突”和“錯(cuò)誤賦值”等問題。
-
- var存在變量提升,可能導(dǎo)致在變量聲明之前就使用變量,產(chǎn)生未定義的情況。
-
- var允許重復(fù)聲明同一變量,容易導(dǎo)致意外修改已有變量的值,引發(fā)代碼錯(cuò)誤。
-
注意:我們最好在創(chuàng)建變量時(shí)就進(jìn)行賦值,這樣可以防止我們的代碼出現(xiàn),聲明了變量但未賦值的情況。
代碼示例:
var old = "";
const immutable = "John";
let counter = 1;
counter++;
const user = {firstname: "John", lastname: "Doe"};
const users = ["Mac", "Roe"];
2.使用嚴(yán)格相等運(yùn)算符(===)
在進(jìn)行相等比較時(shí),只使用嚴(yán)格相等運(yùn)算符(===)進(jìn)行比較。
原因:
-
- 雙等號(hào)(==)在進(jìn)行類型比較時(shí)會(huì)默認(rèn)進(jìn)行類型轉(zhuǎn)換,導(dǎo)致不同類型的值也可能被判定為相等。
-
- 嚴(yán)格相等運(yùn)算符(===)不僅比較兩個(gè)值的值,還會(huì)比較它們的數(shù)據(jù)類型。只有值和類型都相同時(shí)才會(huì)返回 true。
-
注意:在使用雙等號(hào)進(jìn)行0作為假值會(huì)錯(cuò)誤地等于false,
代碼示例:
1 == "1";
0 == false;
"" == 0;
null == undefined;
[1] == true;
"false" == false;
1 === 1;
1 === "1";
0 === false;
3.使用模板字符串來拼接內(nèi)容
使用模板字符串(反引號(hào)標(biāo)記)來拼接字符串,而不是使用加號(hào)(+)。
原因:
-
- 模板字符串允許在字符串中插入變量或表達(dá)式,使得代碼更加清晰易讀。
-
代碼示例:
const name = 'Alice';
const age = 30;
const greeting = 'Hello, my name is ' + name + ' and I am ' + age + ' years old.';
console.log(greeting);
const multiLineString = 'This is a\nmulti-line\nstring.';
console.log(multiLineString);
const greeting = `Hello, my name is ${name} and I am ${age} years old.`;
console.log(greeting);
const multiLineString = ` This is a
multi-line
string. `;
console.log(multiLineString);
4.在語句末尾使用分號(hào)
在行末使用分號(hào)結(jié)尾是一種很好的習(xí)慣,雖然不使用分號(hào),編譯器也不會(huì)進(jìn)行報(bào)錯(cuò),但在我們項(xiàng)目越來越龐大代碼越來越復(fù)雜時(shí),分號(hào)可以幫助我們更好的理解代碼。維護(hù)起來也會(huì)更加輕松。
以for循環(huán)為例:
代碼示例:
for (let i = 0 i < numbers.length i++) {
console.log(numbers[i]);
}
for (let i = 0; i < numbers.length; i++) {
console.log(numbers[i]);
}
在上面的示例中,缺少分號(hào)會(huì)導(dǎo)致編譯器認(rèn)為它是一個(gè)表達(dá)式,但是它實(shí)際上是三個(gè)獨(dú)立不同的表達(dá)式,這樣的結(jié)果就是會(huì)引起報(bào)錯(cuò)。
5. 使用對(duì)象代替多個(gè)參數(shù)
在定義函數(shù)時(shí),給函數(shù)定義多個(gè)參數(shù)的做法是很愚蠢的一種寫法,因?yàn)椋?dāng)需要傳的參數(shù)變的很多很復(fù)雜時(shí),代碼的閱讀和維護(hù)就變的很困難,而使用對(duì)象參數(shù)是一種很好的替代方案。
代碼示例:
function avatarUrl(avatar, format = "small", caption = true,) {
}
avatarUrl(user.avatar, 'thumb', false)
當(dāng)我們?cè)谑褂蒙厦孢@個(gè)函數(shù)時(shí),很難知道哪些參數(shù)被使用了以及他的含義是什么。例如上面avatarUrl的最后一個(gè)參數(shù)false,就很難讓人理解它代表的是什么意思呢?
所以我們?cè)诰S護(hù)時(shí),必須要閱讀完函數(shù)的定義才能知道他的每個(gè)參數(shù)代表什么意思。
而且當(dāng)我們需要改變參數(shù)的順序時(shí),不得不改變所有地方的函數(shù)調(diào)用。
但是如果我們使用對(duì)象來傳參,一個(gè)順序的改變并不會(huì)影響到所有地方的調(diào)用:
function avatarUrl(avatar, options={format: 'small', caption: true}) {
}
avatarUrl(user.avatar, {
caption: false ,
format: "thumb"
})
6. 利用提前返回簡(jiǎn)化邏輯
在編寫代碼時(shí),我們經(jīng)常會(huì)用到if/else來進(jìn)行判斷,而且可能會(huì)進(jìn)行多層嵌套,但是過多過深的嵌套會(huì)使的我們的代碼可讀性變差并且很難維護(hù),所以我們使用return來解決這個(gè)問題。
提前返回可以減少大量的不必要的else條件,提高代碼的可讀性
代碼示例:
function doSomething() {
if (user) {
if (user.role === "ADMIN") {
return 'Administrator';
} else {
return 'User';
}
} else {
return 'Anonymous';
}
}
function doSomething() {
if (!user) return 'Anonymous'
if (user.role === "ADMIN") return 'Administrator'
return 'User'
}
7. 熟練掌握內(nèi)置函數(shù)
JavaScript給我們提供了許多內(nèi)置的Array、Object、String函數(shù)。我們需要精通并掌握它們,這樣讓我們寫起代碼時(shí)來事半功倍。
代碼示例:
const users = [
{
username: "JohnDoe",
admin: false
},
{
username: "Todd",
admin: true
},
];
const admins = [];
function getAdmins() {
users.forEach((user) => {
if (user.admin) admins.push(user)
})
return admins
}
function getAdmins() {
return users.filter((user) => user.admin)
}
8.禁止使用縮寫
當(dāng)初學(xué)者在剛開始編寫代碼時(shí),很容易為了貪圖方便和快,就用縮寫來進(jìn)行命名,雖然這樣是方便的當(dāng)時(shí)的工作,但是卻為后期的維護(hù)埋下了定時(shí)炸彈。讓后續(xù)的代碼閱讀和維護(hù)變的難上加難。
function someFunction() {
events.forEach(e => {
e.tickets.forEach(t => {
`${e.name} for ${t.full_name}`
})
})
}
function someFunction() {
events.forEach(event => {
event.tickets.forEach(ticket => {
`${event.name} for ${ticket.full_name}`
})
})
}
很明顯的是,在下面的例子中我們?cè)陂喿x和維護(hù)時(shí)都不用猜測(cè)參數(shù)e和t代表什么意思和作用,根據(jù)命名就可以知道它的作用和含義。極大的提高了代碼的可讀性和后期的維護(hù)。
9. 使用可選鏈操作符(?.
)來代替&&的前置非空判斷
在遇到對(duì)象的某個(gè)屬性可能為空(null)或者不存在(undefined)時(shí),我們都要提前對(duì)對(duì)象進(jìn)行判空,很多人第一時(shí)間都會(huì)想到使用&&進(jìn)行前置非空判斷,但是其實(shí)遇到這種情況,我們使用可選鏈操作符(?.
也能達(dá)到一樣的效果,并且可讀性更強(qiáng)。
示例1:
function doSomething(params) {
if (params && params.filter) return 'Foo'
return 'Bar'
}
function doSomething(params) {
if (params?.filter) return 'Foo'
return 'Bar'
}
10. 用for...of代替for循環(huán)
傳統(tǒng)的for循環(huán)需要我們手動(dòng)創(chuàng)建索引變量并且需要根據(jù)條件判斷來進(jìn)行遞增/遞減操作,而for...of內(nèi)置了一個(gè)迭代器可以自動(dòng)幫我們遍歷數(shù)組中的所有值,這樣我們的代碼可以變的更加簡(jiǎn)潔,也可以減少手動(dòng)操作出差的情況。
let users = ["Fedor Emelianenko", "Cyril Gane", "Conor McGregor"];
let usersCount = users.length;
for (let i = 0; i < usersCount; i++) {
console.log(users[i]);
}
for(let user of users) {
console.log(user);
}
11. 可讀性代碼勝過聰明代碼