函数式编程vs面向对象编程vs过程式编程的JS演示比较
这是一个真实的例子,展示了三种最常见的编程范式的差异。我将用三种不同的方式解决一个问题。
每个示例将处理表单提交、验证用户输入并将创建的用户打印到控制台。我还添加了保存错误记录器。
案例表单 Document
简单的 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: "", password: ""} // 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 过程式编程的JS演示比较 - DEV
唐山两地网信办开展网络安全检查9月29日,遵化市委网信办组织开展节前网络安全检查。网信办工作人员和网络安全专家组成检查组先后到遵化市发改局市教育局市工信局市城管局等单位,针对网络安全责任制落实情况网络安全日常管
浅谈云计算时代的数据库运行以往,如果企业想要构建灾难恢复(DR)基础设施,那么它就是一个独立的设施。而当涉及到关键数据和应用程序时,本地数据中心是唯一可行的选择。但是用这种方法保持近乎完美的可靠性的代价是非
加强产业协同破解数字化平权困境9月29日当前,云计算正成为数字化转型的关键路径。市场研究公司Canalys近日发布的中国云计算市场2021年第二季度报告显示,中国的云基础设施市场在2021年第二季度增长了54,
谁会成为5G时代杀手级应用?9月27日,2021世界互联网大会乌镇峰会进入第二天,围绕着5G网络安全人工智能等热点主题的分论坛陆续展开,吸引来自各行业领域的专家学者企业高层在会场内外分享观点展开探讨。5G能力
第三届工业信息安全应急国际研讨会在京举办9月29日,第三届工业信息安全应急国际研讨会在北京举办。郑凯在致辞中表示,推动工业信息安全尤其是工业信息安全应急的国际合作已成为各国深化合作的新领域新方向新亮点。希望坚持互学互鉴,
2021阿里云计算峰会上海站在虹桥召开近日,2021阿里云计算峰会上海站在虹桥召开。市经济信息化委副主任张英出席会议。会议以强劲稳定安全为主题,聚集国内云计算领域的专家学者和优秀企业代表,集思广益拓展思维,探讨云计算在
如何应对新时代网络安全新思维新防护推进多方合作随着数字经济发展,网络安全也成为了今年互联网大会关注的一个重点领域,网络安全数据安全成为了大会上的高频词汇。目前世界上还有36亿人无法进入互联网,要促进跨越数字鸿沟,需加强沟通和数
2022年顶级的云计算趋势和预测一些IT专家认为,云计算在未来几年将位于企业解决重大业务挑战的各种技术的前沿。预计从2016年到2026年期间,大型企业的云计算支出将以16的复合年增长率增长,很多企业已经完全将云
手机修图软件Snapseed全新的使用技巧创意篇(五)全新的使用技巧创意篇(五)Snapseed在手机中是非常好的修图软件,已经是许多摄影人的首选,但毕竟不如电脑软件完美,尤其是不能自己制作相框,因此我想到了一种方法,可以制作非常漂亮
如何设置相机参数拍好小清新人像设置好相机参数,拍好小清新。许多人都很喜欢拍一些小清新照片,有淡雅清爽的美丽,有柔和朦胧的温馨。拍摄小清新照片,有三个关键点,一是色彩,二是色温,三是干净,就是说色彩不易过多,色温
手机修图Snapseed技巧,如何正确认识蒙版技能我发现许多人都会使用蒙版,却又不怎么了解蒙版,有些人认为只有使用双重曝光工具,才用到蒙版,有些人认为只有擦除的时候才使用蒙版,还有些人认为点击右上角的箭头就是蒙版,甚至有些教程也是