淺談JavaScript編程過程Function函數的幾種編程風格
聲明
JavaScript編程過程中函數是一個很有趣的點,JavaScript的函數與其他如:C、Java等語言有很大區別。對于從別的編程語言轉來的同學可能會存在一定的“坑”,如function函數與=>函數的區別。function函數this關鍵字的占用等。
在下文的案例中可能會使用這些知識,但我因為篇幅限制將不會對這些語法進行討論,只討論不同編碼方式的風格問題。
測試環境申明
測試工具:DevEco Studio 3.1.1 Release 構建版本:3.1.0.501
測試平臺:HarmonyOS Api9 x86 虛擬機
測試語言:ArkTS(只測試JavaScript語法部分)
簡介
因為JavaScript編程風格的靈活性。在一個簡單的求和函數、在JavaScript中可以使用很多不同的風格表示。
小編將會以函數式編程、面向對象編程、面向對象鏈式編程、申明式編程等多個不同的方式表示出來。
以下代碼僅作為拋磚引玉的效果,不代表實際開發代碼,也不代表當下所有的編碼風格,小編只談論我了解的幾種。在實際開發過程中每一種編碼風格也會存在更多的細分風格。
過程式編程
代碼
// 過程式編程
function add(...is: number[]) {
// 總和
let sum = 0;
// 求和
for (let index = 0; index < is.length; index++)
sum += is[index];
// 返回總和
return sum;
}
/**
* 使用樣例
* console.log(add(11, 22, 33));
*/
解讀
過程式編程是最簡單粗暴直接的編程方式,在所有主流編程語言中都支持使用過程式編程。
過程式編程往往需要編程者擁有過硬的編程素養與對業務的深刻理解才可以保證代碼的持續性的可維護性、可擴展性。
在業務不確定、實現邏輯經常變化、實現方案不穩定的部分不建議使用這種編碼風格,因為它很容易導致代碼失控。
但是在算法實現上,筆者強烈建議各位使用這種編碼風格。它簡單可靠,可以節約編程者的許多心智。
柯里化編程
代碼
// 自動柯里化機,可以自動把函數轉化為柯里化風格。
function curry(fn) {
return function curried(...args) {
if (args.length >= fn.length) {
return fn.apply(this, args);
} else {
return function (...nextArgs) {
return curried.apply(this, args.concat(nextArgs));
}
}
}
}
// 獲得轉化后的函數
export const curriedAdd = curry(add2);
/**
* 使用樣例
* console.log(curriedAdd(1)(2)); // 3
* console.log(curriedAdd(1, 2)); // 3
* console.log(curriedAdd(1)(2, 3)); // 3
*/
解讀
柯里化編程有一個有特色的地方是函數的連續嵌套,這是前端開發非常熱門的一種編程方式。但小編極力反對這種編程方式具體原因有一下幾點:
- 柯里化編程雖然確實提高了開發的靈活性,但是它也降低了函數的可修改性,導致后續重構可能會牽一發而動全身。
- 柯里化有一個很大的特點是函數嵌套,這不符合"never nester"不嵌套主義的編程理念。嵌套會大幅降低可讀性。
如果你真的打算使用柯里化的編程風格。小編建議你,寫全注釋!
一直寫到,我不需要讀你的函數,就知道你這個函數想做什么、有幾個參數、想返回什么、什么情況下會結束柯里化。
面向對象編程風格函數
代碼
// 面向對象風格函數
export function count() {
// 總和屬性
this._sum = 0;
// 添加方法方法
this.add = (i) => this._sum += i;
// 返回總和方法
this.get = () => this._sum;
// 返回構造對象
return this;
}
/*
// 使用樣例
* a = count();
* console.log(a.add(10));
* console.log(a.add(20));
* a.add(30);
* console.log(a.get());
*/
解讀
相對于下文提到的鏈式編程、更加正統的面向對象風格。每一次運算結果清晰、類型明確,在現代化的編程工具幫助下,編程效率很高。
面向對象風格函數、鏈式編程
代碼
//面向對象鏈式編程風格
// 構造函數
export function count2() {
// 總和屬性
this._sum = 0;
// 添加方法
this.add = (is) => ((this._sum += is), this);
// 求和方法
this.get = () => this._sum
// 返回構造對象
return this;
}
/*使用樣例
console.log(count().add(10).add(20).add(30).get());
*/
解讀
我之所以將它從面向對象單獨拎出來,是因為面向對象鏈式風格編程、基本可以代替柯里化編程。
這種編程風格相對于柯里化更加扁平,可讀性更高,還具備一定的可拓展性。
所以,如果在可以選的情況下為什么要使用柯里化呢?
聲明式風格函數
代碼
// 聲明式風格函數
export function sum3(is, get) {
let ans = 0;
// 這里可以使用任何實現方式,可以使用異步等方式實現
is.forEach(element => {
ans += element;
});
// 無論用任何方式實現,最后所有運算結束后都使用get函數作為回調。
get(ans)
}
解讀
聲明式風格的函數特點不在于它代碼是怎樣的,而是在于它提供了哪些參數供開發者調用。開發者不在去關心實現的順序,如何實現、因為如何實現根本不重要,實現順序也不重要。你想要的只有答案,和得到答案。實現可以使用任何方式實現,內部可以使用多線程、異步、或者等等的方法實現。
總結
現代編碼風格的演變,無非就是隨著需要處理問題的改變,產生了關注的點的改變。去改變開發者的注意力,讓開發者放置跟多的精力在自己的業務上。不是越先進的編碼風格就越好用,在合適的地方選擇合適的編碼風格才是最重要的。