这可能有点哲学性,但我认为这是提问的正确地点。
假设我有一个创建 ID 列表的函数。这些标识符仅在应用程序内部使用,因此使用 ES2015 是可以接受的Symbol()
here.
我的问题是,技术上,当您请求一个符号时,我想 JS 运行时会创建一个唯一标识符(随机数?内存地址?不确定),为了防止冲突,需要访问全局状态。我不确定的原因是因为“技术上”这个词。我不确定(再次从哲学的角度来看)这是否足以打破 API 所呈现的数学抽象。
tl;dr:这是一个例子——
function sentinelToSymbol(x) {
if (x === -1) return Symbol();
return x;
}
这个函数是纯函数吗?
不完全是,不,但这实际上可能并不重要。
在表面上,(foo) => Symbol(foo)
显得纯洁。虽然运行时may做一些有副作用的操作,你永远不会看到它们,即使你调用Symbol()
同时具有相同的参数。然而,调用Symbol
使用相同的参数永远不会返回相同的值,这是主要标准之一(#2,如下)。
From MDN 页面:
请注意,Symbol("foo") 不会将字符串“foo”强制转换为符号。它每次都会创建一个新符号:
Symbol("foo") === Symbol("foo"); // false
只看副作用,(foo) => Symbol(foo)
是纯粹的(高于运行时)。
然而,纯函数必须满足更多标准。来自维基百科:
纯函数(或表达式)没有副作用(内存或 I/O)。这意味着纯函数具有几个有用的属性,其中许多属性可用于优化代码:
- 如果不使用纯表达式的结果,则可以将其删除而不影响其他表达式。
- 如果使用不会引起副作用的参数调用纯函数,则结果相对于该参数列表是恒定的(有时称为引用透明性),即,如果使用相同的参数再次调用纯函数,则将得到相同的结果返回(这可以启用缓存优化,例如记忆)。
- 如果两个纯表达式之间不存在数据依赖关系,那么它们的顺序可以颠倒,或者可以并行执行并且不能相互干扰(换句话说,任何纯表达式的求值都是线程安全的)。
- 如果整个语言不允许副作用,那么可以使用任何评估策略;这使编译器可以自由地重新排序或组合程序中表达式的计算(例如,使用毁林)。
你可能会认为该列表的前言排除了这一点一切在 JavaScript 中,因为任何操作都可能导致内存分配、内部结构更新等。按照最严格的解释,JS 从来都不是纯粹的。这不是很有趣或有用,所以......
该函数满足标准#1。不考虑结果,(foo) => Symbol(foo)
and (foo) => ()
与任何外部观察者都是相同的。
标准#2 给我们带来了更多麻烦。给定bar = (foo) => Symbol(foo)
, bar('xyz') !== bar('xyz')
, so Symbol
根本不符合这个要求。您每次调用时都保证会得到一个唯一的实例Symbol
.
继续,标准#3 不会造成任何问题。您可以致电Symbol
来自不同线程,不会发生冲突(并行),并且调用它们的顺序并不重要。
最后,标准 #4 比直接要求更重要,并且很容易满足(JS 运行时会随机调整所有内容)。
所以:
- 严格来说,JS 中没有什么是纯粹的。
-
Symbol()
绝对不是纯粹的,因此这个例子也不是。
- 如果您关心的只是副作用而不是记忆,那么该示例确实符合这些标准。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)