### 1. 使用箭頭函數簡化函數定義 ```cobol // 傳統函數定義 function add(a, b) { return a + b; } // 箭頭函數簡化 const add = (a, b) => a + b; ``` ### 2. 使用解構賦值簡化變數聲明 ```cobol // ...
1. 使用箭頭函數簡化函數定義
// 傳統函數定義
function add(a, b) {
return a + b;
}
// 箭頭函數簡化
const add = (a, b) => a + b;
2. 使用解構賦值簡化變數聲明
// 傳統變數聲明
const firstName = person.firstName;
const lastName = person.lastName;
// 解構賦值簡化
const { firstName, lastName } = person;
3. 使用模板字面量進行字元串拼接
// 傳統字元串拼接
const greeting = 'Hello, ' + name + '!';
// 模板字面量簡化
const greeting = `Hello, ${name}!`;
4. 使用展開運算符進行數組和對象操作
// 合併數組
const combined = [...array1, ...array2];
// 複製對象
const clone = { ...original };
5. 使用數組的高階方法簡化迴圈和數據操作
// 遍曆數組並返回新數組
const doubled = numbers.map(num => num * 2);
// 過濾數組
const evens = numbers.filter(num => num % 2 === 0);
6. 使用條件運算符簡化條件判斷
// 傳統條件判斷
let message;
if (isSuccess) {
message = 'Operation successful';
} else {
message = 'Operation failed';
}
// 條件運算符簡化
const message = isSuccess ? 'Operation successful' : 'Operation failed';
7. 使用對象解構和預設參數簡化函數參數
// 傳統參數設置預設值
function greet(name) {
const finalName = name || 'Guest';
console.log(`Hello, ${finalName}!`);
}
// 對象解構和預設參數簡化
function greet({ name = 'Guest' }) {
console.log(`Hello, ${name}!`);
}
8. 使用函數式編程概念如純函數和函數組合
// 純函數
function add(a, b) {
return a + b;
}
// 函數組合
const multiplyByTwo = value => value * 2;
const addFive = value => value + 5;
const result = addFive(multiplyByTwo(3));
9. 使用對象字面量簡化對象的創建和定義
// 傳統對象創建
const person = {
firstName: 'John',
lastName: 'Doe',
age: 30,
};
// 對象字面量簡化
const firstName = 'John';
const lastName = 'Doe';
const age = 30;
const person = { firstName, lastName, age };
10. 使用適當的命名和註釋來提高代碼可讀性
// 不好的
const x = 10; // 設置x的值為10
function a(b) {
return b * 2; // 返回b的兩倍
}
// 好的
const speed = 10; // 設置速度為10
function double(value) {
return value * 2; // 返回輸入值的兩倍
11. 優雅的寫條件判斷代碼
簡單的條件判斷邏輯用if else
或者 三元運算符, 一眼看過去還能知道說的啥,但是大量的if else
和疊加在一起的三元運算符就是接盤俠的噩夢~~~
給大家上一個三元運算符疊加的案例,我是真實在項目中遇到過,cpu直接乾爆~~~
<view>{{status===1?'成功': status===2 ? '失敗' : status===3 ? '進行中' : '未開始' }}</view>
大概是這樣的,具體的項目代碼不好放在這裡,小伙伴們意會就行。
複雜邏輯推薦使用對象Map寫法,符合人腦的邏輯,可讀性高,看著舒服~~~
1,普通的if else
let txt = '';
if (falg) {
txt = "成功"
} else {
txt = "失敗"
}
2,三元運算符
let txt = flag ? "成功" : "失敗";
3,多個if else
// param {status} status 活動狀態:1:成功 2:失敗 3:進行中 4:未開始
let txt = '';
if (status == 1) {
txt = "成功";
} else if (status == 2) {
txt = "失敗";
} else if (status == 3) {
txt = "進行中";
} else {
txt = "未開始";
}
4,switch case
let txt = '';
switch (status) {
case 1:
txt = "成功";
break;
case 2:
txt = "成功";
break;
case 3:
txt = "進行中";
break;
default:
txt = "未開始";
}
5,對象寫法
const statusMap = {
1: "成功",
2: "失敗",
3: "進行中",
4: "未開始"
}
//調用直接 statusMapp[status]
5,Map寫法
const actions = new Map([
[1, "成功"],
[2, "失敗"],
[3, "進行中"],
[4, "未開始"]
])
// 調用直接 actions.get(status)
12. 封裝條件語句
同上,if里的條件越多越不利於接盤俠的維護,不利於人腦的理解,一眼看過去又是一堆邏輯。多個邏輯應該化零為整
。
大腦:'別來碰我,讓我靜靜'
// 不好的
if (fsm.state === 'fetching' && isEmpty(listNode)) {
// ...
}
// 好的
shouldShowSpinner(fsm, listNode){
return fsm.state === 'fetching' && isEmpty(listNode)
}
if(shouldShowSpinner(fsm, listNode)){
//...doSomething
}
13. 函數應該只做一件事
函數式寫法推崇柯里化
, 一個函數一個功能,可拆分可組裝。
// 不好的
function createFile(name, temp) {
if (temp) {
fs.create(`./temp/${name}`);
} else {
fs.create(name);
}
}
// 好的
function createFile(name) {
fs.create(name);
}
function createTempFile(name) {
createFile(`./temp/${name}`)
}
再來一個慄子
函數要做的事情如下:
- 遍歷clients數組
- 遍歷過程中,通過lookup函數得到一個新的對象clientRecord
- 判斷clientRecord對象中isActive函數返回的是不是true,
-
- isActive函數返回true,執行email函數並把當前成員帶過去
// 不好的
function emailClients(clients) {
clients.forEach((client) => {
const clientRecord = database.lookup(client);
if (clientRecord.isActive()) {
email(client);
}
});
}
// 好的
function emailClients(clients) {
clients
.filter(isClientRecord)
.forEach(email)
}
function isClientRecord(client) {
const clientRecord = database.lookup(client);
return clientRecord.isActive()
}
上面不好的慄子一眼看過去是不是感覺一堆代碼在那,一時半會甚至不想去看了。
好的慄子,是不是邏輯很清晰,易讀。
- 巧用filter函數,把filter的回調單開一個函數進行條件處理,返回符合條件的數據
- 符合條件的數據再巧用forEach,執行email函數
14. Object.assign給預設對象賦預設值
// 不好的
const menuConfig = {
title: null,
body: 'Bar',
buttonText: null,
cancellable: true
};
function createMenu(config) {
config.title = config.title || 'Foo';
config.body = config.body || 'Bar';
config.buttonText = config.buttonText || 'Baz';
config.cancellable = config.cancellable === undefined ?
config.cancellable : true;
}
createMenu(menuConfig);
// 好的
const menuConfig = {
title: 'Order',
buttonText: 'Send',
cancellable: true
};
function createMenu(config) {
Object.assign({
title: 'Foo',
body: 'Bar',
buttonText: 'Baz',
cancellable: true
}, config)
}
createMenu(menuConfig);
15. 函數參數兩個以下最好
說一千道一萬,就是為了優雅,就是為了可讀性好。
// 不好的
function createMenu(title, body, buttonText, cancellable) {
// ...
}
// 好的
const menuConfig = {
title: 'Foo',
body: 'Bar',
buttonText: 'Baz',
cancellable: true
};
function createMenu(config){
// ...
}
createMenu(menuConfig)
16. 使用解釋性的變數
省流,用了擴展運算符,為了可讀性(saveCityZipCode(city, zipCode)
可讀性很好,知道參數是幹嘛的)
// 不好的
const address = 'One Infinite Loop, Cupertino 95014';
const cityZipCodeRegex = /^[^,\\]+[,\\\s]+(.+?)\s*(\d{5})?$/;
saveCityZipCode(address.match(cityZipCodeRegex)[1], address.match(cityZipCodeRegex)[2]);
// 好的
const address = 'One Infinite Loop, Cupertino 95014';
const cityZipCodeRegex = /^[^,\\]+[,\\\s]+(.+?)\s*(\d{5})?$/;
cosnt [, city, zipCode] = address.match(cityZipCodeRegex) || [];
saveCityZipCode(city, zipCode)
想對類中的屬性進行更多自定義取/增/改的操作時,使用set/get
第一次見這個寫法,不知道是啥意思的小伙伴,把他當成vue2中的defineProperty
Object.defineProperty(data1,'age',{
set:function(newAge){
console.log(this.name+'現在'+newAge+'歲')
},
get:function(){
return 18;
}
})
是一個意思,賦值的時候set會被觸發,取值的時候get會被觸發。
巧用自帶屬性,提升性能。
class BankAccount {
constructor(balance = 1000) {
this._balance = balance;
}
// It doesn't have to be prefixed with `get` or `set` to be a
//getter/setter
set balance(amount) {
console.log('set')
if (verifyIfAmountCanBeSetted(amount)) {
this._balance = amount;
}
}
get balance() {
console.log('get')
return this._balance;
}
verifyIfAmountCanBeSetted(val) {
// ...
}
}
const bankAccount = new BankAccount();
// Buy shoes...
bankAccount.balance -= 100;
// Get balance
let balance = bankAccount.balance;
17. 讓對象擁有私有成員-通過閉包來實現
閉包天生就是做私有化的
// 不好的
const Employee = function(name) {
this.name = name;
};
Employee.prototype.getName = function getName() {
return this.name;
};
const employee = new Employee('John Doe');
console.log(`Employee name: ${employee.getName()}`); // Employee name: John Doe
delete employee.name;
console.log(`Employee name: ${employee.getName()}`); // Employee name: undefined
// 好的
const Employee = function(name){
this.getName = function(){
return name
}
}
const employee = new Employee('John Doe');
console.log(`Employee name: ${employee.getName()}`); // Employee name: John Doe
delete employee.name;
console.log(`Employee name: ${employee.getName()}`); // Employee name: undefined
第一個示例
優點:
- 通過
原型鏈共用方法
,節省了記憶體空間。所有實例對象共用同一個getName
方法,而不是每個實例對象都創建一個獨立的方法。
缺點:
- 在構造函數中無法直接定義私有屬性或方法,
所有屬性和方法都會被暴露在原型鏈上
。
第二個示例
優點:
- 可以在構造函數內部
定義私有屬性和方法
,不會暴露在對象的原型鏈上,提供了更好的封裝性。
缺點:
- 每次創建實例對象時,都會創建一個獨立的方法,
每個實例對象都有
自己的getName
方法,占用更多的記憶體空間。
18. 使用方法鏈
鏈式寫法
也是代碼優雅之道的重頭戲。
ps:發明這個的程式員肯定是後端出身的,這種寫法在PHP的CI框架中見過。
// 不好的
class Car {
constructor() {
this.make = 'Honda';
this.model = 'Accord';
this.color = 'white';
}
setMake(make) {
this.make = make;
}
save() {
console.log(this.make, this.model, this.color);
}
}
const car = new Car();
car.setMake('Ford');
car.save();
// 好的
class Car {
constructor() {
this.make = 'Honda';
this.model = 'Accord';
this.color = 'white';
}
setMake(make) {
this.make = make;
// NOTE: return this是為了用鏈式寫法
return this;
}
save() {
console.log(this.make, this.model, this.color);
// NOTE:return this是為了用鏈式寫法
return this;
}
}
const car = new Car()
.setMake('Ford')
.save();
看完上面的這麼多慄子,小伙伴的思路是不是清晰了很多,在你們的項目里練練手吧。