这是一个真实的例子,展示了三种最常见的编程范式的差异。我将用三种不同的方式解决一个问题。
每个示例将处理表单提交、验证用户输入并将创建的用户打印到控制台。我还添加了保存错误记录器。
案例表单
<!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> </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 Logger { static logs = [] static showAlert(message) { this.logs.push(message) alert(message) } } 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 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 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', } const validate = (value, flag, validatorValue) => { switch(flag){ case FLAGS.minLength: return value.trim().length >= validatorValue case FLAGS.hasDigit: return !!value.match(/[0-9]/) } } const setFormSubmitHandler = (formId, onSubmit) => { const form = document.getElementById(formId) form.addEventListener('submit', onSubmit) } 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 }), {} ) } 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 } } 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 过程式编程的JS演示比较 – DEV
2024最新激活全家桶教程,稳定运行到2099年,请移步至置顶文章:https://sigusoft.com/99576.html
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。
文章由激活谷谷主-小谷整理,转载请注明出处:https://sigusoft.com/16635.html