我知道纯函数属于“函数式编程”范例,你创建一个没有任何副作用的函数,对于输入它总是返回相同的输出,如:
function (a,b) {
return a + b;
}
这是一个纯函数,因为对于输入我总是返回相同的输出而我没有产生任何副作用。好的我明白了。
但是如何制作“纯函数”,当我真正想要创建副作用时,如何保持“函数式编程”范式,例如更改DOM中的文本内容,如:
function changeContent () {
let content = document.querySelector("#content");
content.textContent = 'Hello World';
}
这个函数有副作用,它没有得到输入返回输出,它产生副作用,但这实际上是函数的要点。这还是“功能性编程”吗?在这种情况下如何保持“函数式编程”范式?
答案 0 :(得分:2)
我如何保持"功能编程"范式,当我真的想创造一个副作用?
你不能真的。纯函数不得有任何副作用。
当然,这意味着我们实际上无法对作为纯函数执行任何操作的程序进行建模。有两种方法:
牺牲纯度。只需编写一个带副作用的函数。彻底记录,以便每个使用该功能的人都知道这一点。对程序的必要部分有不同的理由。
这是大多数编程语言的首选解决方案,因为它们不会强制执行纯度,而且您通常可以随时使用它。
构建一个(纯)数据结构,明确描述您希望程序拥有的效果。然后有一个不纯的"翻译"将它们执行到"运行"你的计划。 (我在这里不详细说明这样的数据结构如何工作,有不同的方法,解释超出了问题的范围)。
在Haskell中,它强制执行所有函数的纯度,这个数据结构是IO
类型,基本上描述了命令式计算,并且它的解释器构建在运行时中。
在JavaScript中,没有这样的解释器。你可以自己构建一个(或使用为此目的而构建的库),但最终你必须在你的程序中的某个地方调用它的run
函数,这会将你带回#1。
对于DOM具体来说:用于描述文档中的更改的数据结构将相对容易构建。您甚至可以引入纯粹的功能优化,例如:将避免多次写入同一位置,或者无论如何都会被删除。
但是,DOM是JavaScript异步性质的基本组成部分。描述与可能的输入和输出的潜在并发交互很难。
答案 1 :(得分:0)
我不确定它是否有用,但您可以将DOM内容传递给该函数并获取一个新内容。像这样:
function changeContent(content, value) {
let result = deepcopy(content); //copy the passed object to preserve it from modifying
result.textContent = value; //change smth in copied object
return result;
}
deepcopy是一个返回对象副本的函数(如果直接设置result = content,那么在结果对象中更改某些值也会导致更改内容对象中的值)。 注意:deepcopy不是内置函数,您应该自己编写或使用库。
P.S。如果这个答案没有用,你可以阅读一篇关于函数式编程的文章here