JavaScript中身份函数的使用

7

我在所有的 JavaScript 程序中都使用恒等函数(identity function):

function identity(value) {
    return value;
}

原因在于我经常需要区分基础类型(undefinednullbooleannumberstring)和由 typeof 运算符返回的对象类型(objectfunction)。我认为,在这种情况下使用身份函数非常简明:

if (new identity(value) == value); // value is of an object type
if (new identity(value) != value); // value is of a primitive type

身份函数比下面的代码要小得多,也要简单得多:
function isObject(value) {
    var type = typeof value;
    return type == "object" || type == "function";
}

然而,我的一个朋友读了我的代码后抱怨说我的方法是误导性的,并且比上面的替代方法更加计算量大。

我不想从任何一个程序中删除这个函数,因为我认为这是一种优雅的hack。但是,我并不是只为自己写程序。在JavaScript中,还有其他用例可以使用identity函数吗?


4
为什么不直接使用 value === Object(value) 呢?或者,为了让代码更易读,定义一个 isObject 函数来使用它呢? - Keen
2
@Cory - 我只是想找到一个实际使用身份函数的案例。我手头有太多时间,所以我用了一种有趣的方式来提出这个问题,以吸引人们的注意,并不会让自己显得像个愚蠢的白痴在问身份函数的用例。 - Aadit M Shah
7
其中最好的用途之一是使可能或不可能应用函数的代码始终能够正常工作:var func = optionalProcessFunc || identityFunc;。现在在代码后面,您无需了解如何配置此部分以运行。更普遍地说,如果您想将函数视为单子,使用恒等函数作为mzero和组合作为mconcat会很方便。 - Keen
{x: 123} != {x:123},在JS中,默认情况下对象不相等,因为它们具有不同的引用。为什么从身份函数返回一个对象时,与该函数本身进行比较会评估为true?我以为构造函数会返回新对象。 - Anton
2个回答

23

在我看来:

new identity(value) == value

如果没有额外的注释,"means absolutely nothing" 没有任何意义,我需要一段时间来确定作者的真实意图。另一方面:

isObject(value)

从一开始就很明显,无论如何实现。为什么不能在名为isObject()的函数内部使用您的hack呢?
顺便说一下,更适合http://codereview.stackexchange.com

new identity(value)是一个不错的小技巧。JavaScript引擎只有在构造函数没有显式返回一个对象(即类型为 objectfunction 的值)时才会返回构造函数的实例。因此,new identity(value)始终是一个对象。因此,当value是对象时,new identity(value) == value才能返回true 。这是因为JavaScript中的相等运算符总是在其中一个操作数是对象时检查identity。好玩的双关语,对吧? - Aadit M Shah
4
我很感激(顺便说一下,使用“===”可能会更快),我相信这个方法是有效的。我的意思是,即使它运行得再快,许多人,包括我自己,也不知道它在做什么。而且(惊喜!)你编写的软件是为人们服务的,而不是为计算机服务的。 - Tomasz Nurkiewicz
1
是的,这也是我朋友说的。但是当你有空闲时间并且没有更好的事情可做时,尝试使用现有技术进行奇怪和创新的方式是很有趣的。 - Aadit M Shah
顺便说一句,你是正确的。使用严格相等确实可以提高性能。谢谢。 - Aadit M Shah
更不用说,你需要在使用它的每个地方都添加注释。撇开Kay发现的正确性问题,我认为这种情况的礼仪应该是——如果你是唯一的维护者,那就去做吧。如果你在一个团队中,isObject是优雅的选择:它自我记录,隐藏了其实现,不需要了解JavaScript的丑陋部分。PHP的“变量变量”优雅吗? - johncip

13

我更新了我的"速度测试",以测试是否返回正确的结果...但它们没有:

如果你将new identity(x) == x进行比较,那么null会被视为对象。不过使用 === 是可以工作的。

这样的陷阱支持使用 isObject(...) 解决方案。

如果你在 isObject 代码中比较 === 'object'/'function',那么它将比原始实现快两倍几乎快三分之一,


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接