不是真的,不,但它可能并不重要。
表面上,(foo) => Symbol(foo)
显得纯洁。虽然运行时可能会执行一些带有副作用的操作,但您永远不会看到它们,即使您Symbol()
同时使用相同的参数调用也是如此。但是,Symbol
使用相同的参数调用将永远不会返回相同的值,这是主要标准之一(下面的#2)。
从MDN 页面:
请注意, Symbol("foo") 不会将字符串 "foo" 强制转换为符号。它每次都会创建一个新符号:
Symbol("foo") === Symbol("foo"); // false
只看副作用,(foo) => Symbol(foo)
是纯粹的(在运行时之上)。
但是,纯函数必须满足更多标准。来自维基百科:
纯函数式函数(或表达式)没有副作用(内存或 I/O)。这意味着纯函数有几个有用的属性,其中许多可以用来优化代码:
- 如果没有使用纯表达式的结果,可以将其删除,而不影响其他表达式。
- 如果一个纯函数使用没有副作用的参数调用,则结果相对于该参数列表是恒定的(有时称为引用透明性),即如果再次使用相同的参数调用纯函数,则相同的结果将是返回(这可以启用缓存优化,例如记忆化)。
- 如果两个纯表达式之间没有数据依赖关系,那么它们的顺序可以颠倒,或者它们可以并行执行并且它们不会相互干扰(换句话说,任何纯表达式的求值都是线程安全的)。
- 如果整个语言不允许副作用,则可以使用任何评估策略;这使编译器可以自由地重新排序或组合程序中表达式的评估(例如,使用森林砍伐)。
您可能会争辩说,该列表的前言排除了JavaScript 中的所有内容,因为任何操作都可能导致分配内存、更新内部结构等。在最严格的解释中,JS 绝不是纯粹的。这不是很有趣或有用,所以...
此功能符合标准#1。无视结果,(foo) => Symbol(foo)
与(foo) => ()
任何外部观察者相同。
标准 #2 给我们带来了更多麻烦。给定bar = (foo) => Symbol(foo)
, bar('xyz') !== bar('xyz')
, 所以Symbol
根本不满足这个要求。保证每次调用时都会返回一个唯一的实例Symbol
。
继续前进,标准#3 没有问题。您可以Symbol
从不同的线程调用而不会发生冲突(并行),并且调用它们的顺序无关紧要。
最后,标准#4 比直接要求更重要,并且很容易满足(JS 运行时会在运行时随机播放所有内容)。
所以:
- 严格来说,JS 中没有什么是纯的。
Symbol()
绝对不是纯粹的,因此这个例子也不是。
- 如果您只关心副作用而不是记忆,那么该示例确实符合这些标准。