函數語言程式設計 vs 物件導向程式設計 vs 程式式程式設計的JS演示比較 - DEV
這是一個真實的例子,展示了三種最常見的程式設計正規化的差異。我將用三種不同的方式解決一個問題。
每個示例將處理表單提交、驗證使用者輸入並將建立的使用者列印到控制檯。我還新增了儲存錯誤記錄器。
案例表單
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Document</title> <!-- <script src="procedural.js" defer></script> --> <!-- <script src="oop.js" defer></script> --> <!-- <script src="functional.js" defer></script> --> </head> <body> <form id="user-form"> <div> <label for="username">Username</label> <input id="username" /> </div> <div> <label for="password">Password</label> <input id="password" type="password" /> </div> <button type="submit">Submit</button> </form> </body> </html> |
簡單的 HTML 登入表單,它將包含三個js不同正規化的有效檔案。
過程化程式設計
程式式程式設計只是一步一步地解決問題。這是完全有效的編碼方式,但是當您希望應用程式擴充套件時它有許多缺點。
const form = document.querySelector('form') const logs = [] form.addEventListener('submit', e => { e.preventDefault() const username = e.target.elements.username.value const password = e.target.elements.password.value let error = '' if (username.trim().length < 3) error = 'Username must be at least 3 characters long' else if (!password.match(/[0-9]/)) error = 'Password must contain at least one digit' if (error) { logs.push(error) alert(error) return } const user = { username, password, } console.log(user) console.log(logs) }) |
簡單一步一步解決問題。但它根本不可重用和可擴充套件。儘管它對於解決此類問題完全有效,並且您將看到它比其他問題要短得多。
物件導向程式設計
物件導向程式設計 ( OOP ) 是最接近現實世界的,因此很容易讓您思考。我們檢視將其劃分為Object的程式碼,其中每個都只完成它的工作。在OOP 中學習的有用概念是SOLID。
// Class responsible only for logging class Logger { static logs = [] static showAlert(message) { this.logs.push(message) alert(message) } } // Class responsible only for validating input class Validator { static flags = { minLength: 'MIN-LENGTH', hasDigit: 'HAS-DIGIT', } static validate(value, flag, validatorValue) { if (flag === this.flags.minLength) { return value.trim().length >= validatorValue } if (flag === this.flags.hasDigit) { return value.match(/[0-9]/) } } } // Class responsible only for creating valid user class User { constructor(username, password) { if (!Validator.validate(username, Validator.flags.minLength, 3)) throw new Error('Username must be at least 3 characters long') if (!Validator.validate(password, Validator.flags.hasDigit)) throw new Error('Password must contain at least one digit') this.username = username this.password = password } } // Class responsible only for from handling class FormHandler { constructor(formElement) { this.form = formElement this.form.addEventListener('submit', this.handleSubmit.bind(this)) } handleSubmit(e) { e.preventDefault() const username = e.target.elements.username.value const password = e.target.elements.password.value try { const user = new User(username, password) console.log(user) console.log(Logger.logs) } catch (err) { Logger.showAlert(err) } } } const form = document.querySelector('form') new FormHandler(form) |
現在你可以明白我將問題劃分為Objects 的意思了:
- FormHandler是它自己的類,負責處理表單。
- User是另一個負責建立使用者並使用Validator類驗證輸入的類。
- 如果有錯誤,Logger類用於顯示警報並儲存日誌。
正如你所看到的,有更多的程式碼,看起來更復雜……那麼為什麼有人會喜歡這個?
酷的是,現在我們可以將它用於任何類似的形式,只需呼叫:
new FormHandler(new_form) |
因此,它可以在包含此指令碼的每個檔案中重複使用。而且它很容易擴充套件,因為一切都被分成只做一件事的塊(單一責任原則)。
函數語言程式設計
非常流行,而且非常簡單。請注意,這並不意味著它無論如何都更好。儘管某些範例可能對某些問題更好,但使用哪個完全取決於您。
const FLAGS = { minLength: 'MIN-LENGTH', hasDigit: 'HAS-DIGIT', } // Function that handles validation const validate = (value, flag, validatorValue) => { switch(flag){ case FLAGS.minLength: return value.trim().length >= validatorValue case FLAGS.hasDigit: return !!value.match(/[0-9]/) } } // Function that sets submit handler const setFormSubmitHandler = (formId, onSubmit) => { const form = document.getElementById(formId) form.addEventListener('submit', onSubmit) } // Function that returns values of required fields as object // In this case it will return {username: "<value>", password: "<value>"} // It might look scary but keep in mind that it's completely reusable const getFormValues = (e, ...fields) => { const values = Object.entries(e.target.elements) const filteredValues = values.filter(([key]) => fields.includes(key)) return filteredValues.reduce( (acc, [key, { value }]) => ({ ...acc, [key]: value }), {} ) } // Function that creates valid user const createUser = (username, password) => { if (!validate(username, FLAGS.minLength, 3)) throw new Error('Username must be at least 3 characters long') if (!validate(password, FLAGS.hasDigit)) throw new Error('Password must contain at least one digit') return { username, password } } // Function that creates logger object with *logs* and *showAlert* function const logger = (() => { const logs = [] return { logs, showAlert: message => { logs.push(message) alert(message) }, } })() // Main function const handleSubmit = e => { e.preventDefault() const { username, password } = getFormValues(e, 'username', 'password') try { const user = createUser(username, password) console.log(user) console.log(logger.logs) } catch (error) { logger.showAlert(error) } } setFormSubmitHandler('user-form', handleSubmit) |
正如您在函數語言程式設計中看到的,我們希望使用小的(理想情況下是純函式)函式來解決問題。這種方法也非常具有可擴充套件性,並且函式可以重用。
純函式是一種沒有難以追蹤的副作用的函式。純函式應該只依賴於給定的引數。
結論
沒有更好和更壞的正規化。有經驗的開發人員可以看到每個的優點,併為給定的問題選擇最好的。
程式式程式設計並不是說你不能使用函式,函數語言程式設計也不會阻止你使用“類”。這些正規化只是幫助以一種隨著程式碼增長而有益的方式來解決問題。
相關文章
- 函數語言程式設計 VS 物件導向程式設計函數程式設計物件
- 物件導向 vs. 函數語言程式設計物件函數程式設計
- 物件導向變成 VS 函數語言程式設計物件函數程式設計
- 物件導向與函式程式設計的比較物件函式程式設計
- Reactor事件驅動的兩種設計實現:物件導向 VS 函數語言程式設計React事件物件函數程式設計
- 函數語言程式設計-鏈式程式設計RAC函數程式設計
- 物件導向的程式設計和函數語言程式設計基本相同的證據 - vavr物件程式設計函數VR
- 為什麼說物件導向程式設計和函數語言程式設計都有問題物件程式設計函數
- 物件導向程式設計-java語言 第二週程式設計題物件程式設計Java
- js物件導向程式設計JS物件程式設計
- Facebook 開源 Skip 物件導向+函數語言程式設計語言物件函數程式設計
- iOS鏈式程式設計及函數語言程式設計iOS程式設計函數
- JS物件導向的程式設計JS物件程式設計
- JS物件導向程式設計(二):建構函式JS物件程式設計函式
- 物件導向程式設計風格 VS 基於物件程式設計風格(boost::bind/function)物件程式設計Function
- 程式程式碼進化的一些思考:從物件導向到設計模式,到函數語言程式設計物件設計模式函數程式設計
- 開放出版:許式偉《Go語言程式設計》樣章“物件導向程式設計”Go程式設計物件
- JS物件導向程式設計(一):物件JS物件程式設計
- 物件導向程式設計物件程式設計
- .NET併發程式設計-函數語言程式設計程式設計函數
- 函數語言程式設計函數程式設計
- JavaScript建構函式,物件導向程式設計JavaScript函式物件程式設計
- 物件-函數語言程式設計簡史物件函數程式設計
- JavaScript 函數語言程式設計導論JavaScript函數程式設計
- Scala 函數語言程式設計(一) 什麼是函數語言程式設計?函數程式設計
- JS物件導向程式設計(三):原型JS物件程式設計原型
- 物件導向程式設計和`GP`泛型程式設計物件程式設計泛型
- JavaScript函數語言程式設計之pointfree與宣告式程式設計JavaScript函數程式設計
- [.net 物件導向程式設計基礎] (2) 關於物件導向程式設計物件程式設計
- OOC 物件導向 C 語言程式設計實踐物件程式設計
- 函數語言程式設計:Lambda 表示式函數程式設計
- 十三、物件導向程式設計物件程式設計
- 程式設計思想 物件導向程式設計物件
- 十六、物件導向程式設計物件程式設計
- perl 物件導向程式設計物件程式設計
- LotusScript物件導向程式設計物件程式設計
- Javascript 物件導向程式設計JavaScript物件程式設計
- Scala函式與函數語言程式設計函式函數程式設計