如何在JS中检查一个值是否是Symbol?
我没有看到
Symbol.isSymbol(x)
方法。我的(x instanceof Symbol)
测试似乎也不起作用。
用 typeof 检查一下:
typeof x === 'symbol'
2022 年更新:采用已接受的答案! 如果您在一个过时的环境中工作,
Symbol
需要进行填充, 那么您已经知道了。你会非常痛苦地意识到这一点。你会被它“困扰”。那么,当然,使用我的答案。否则别打扰。 typeof x === 'symbol'
几乎绝对是您现在所需要的。
在 ES 2015 及更高版本中,只需要 typeof x === 'symbol'
即可。但如果您将代码转译为 ES 5.1 或更早版本,即使您使用内置的
Symbol
填充,它也不起作用。我见过的每个 polyfill,包括 babel-polyfill,都使用名为 typeof x === 'object'
的构造函数将 Symbol 实现为对象(即
Symbol
)。因此,在这些情况下,您可以检查Object.prototype.toString.call (x) === '[object Symbol]'
*。把它们放在一起,我们得到:
function isSymbol (x) {
return typeof x === 'symbol'
|| typeof x === 'object' && Object.prototype.toString.call (x) === '[object Symbol]';
}
instanceof
。
instanceof
的问题在于,它只对在与断言相同的全局上下文中创建的对象返回 true。因此,如果网络工作者将一个符号传递回您的页面,或者在 iframe 之间传递符号,那么 x instanceof Symbol
将返回 false!对于所有对象类型(包括内置对象)始终都是如此。 instanceof
通常工作得很好,但如果您的代码有可能处于我所描述的“多帧”场景中,请谨慎使用!
const result = (value && value.constructor === Symbol);
typeof value=="symbol"
但是您可能不想依赖
typeof
,因为对于已转换为对象的符号,它将返回
"object"
。这些符号仍然在各个方面发挥着符号的作用,不应该被忽视。对于 ES6 之前的浏览器进行了多填充的符号在使用 "object"
时也会返回
typeof
,因为 "symbol"
的返回类型在 ES6 之前尚不可用。在这种情况下,使用 instanceof
可能是你最好的选择:
Object(value) instanceof Symbol;// works in most cases
上面的方法比下面的最后一个方法更快,因为 try/catch 需要额外的开销。然而,
instanceof
在某些情况下会失败,例如在不同窗口或框架中创建的对象,因此在不同的全局环境中。
这里有一个方法可以解决以上所有问题。它可以与符号原语、无论全局环境如何都转换为对象的符号以及设计用于 ES6 之前的 JavaScript 的 polyfilledSymbol
一起使用。它起作用的原因是因为如果传递的值既不是符号也不是符号对象,
Symbol.prototype.toString()
将会抛出异常。// Annoyingly complex, yet guaranteed to work
function isSymbol(value) {
try {
Symbol.prototype.toString.call(value)// Throws if value is not a Symbol primitive or object
var isSymbol = 1;// This is only set if it didn't throw
}
catch(e) {
}
return !!isSymbol;// cast to boolean
}