获取 Javascript 变量类型的更好方法?

IT技术 javascript types typeof
2021-01-25 04:11:34

有没有比 JS 更好的方法来获取变量的类型typeof当你这样做时它工作正常:

> typeof 1
"number"
> typeof "hello"
"string"

但是当你尝试时它是没用的:

> typeof [1,2]
"object"
>r = new RegExp(/./)
/./
> typeof r
"function"

我知道instanceof,但这需要您事先知道类型。

> [1,2] instanceof Array
true
> r instanceof RegExp
true

有没有更好的办法?

6个回答

Angus Croll 最近写了一篇关于这个的有趣的博客文章 -

http://javascriptweblog.wordpress.com/2011/08/08/fixing-the-javascript-typeof-operator/

他分析了各种方法的优缺点,然后定义了一个新方法“toType”——

var toType = function(obj) {
  return ({}).toString.call(obj).match(/\s([a-zA-Z]+)/)[1].toLowerCase()
}
如果您的类型命名包含 : 或 _ 您可以将此正则表达式扩展为 match(/\s([a-z,_,:,A-Z]+)/)
2021-03-17 04:11:34
我建议改用\w运算符这个词……
2021-03-28 04:11:34
这里有趣的旁注 - 这可能会破坏将“主机”对象传递给函数的地方。ActiveXObject例如,Internet Explorer实例。
2021-04-06 04:11:34
如果您创建了自己的对象类型(原型继承),您如何让它返回比“对象”更具体的值?这也作为一个问题在这里提出,但从未得到解决。
2021-04-09 04:11:34
正则表达式还需要包含诸如Uint8Array. 相反,考虑match(/\s([^\]]+)/)应该处理任何事情的更一般的
2021-04-10 04:11:34

您可以尝试使用constructor.name.

[].constructor.name
new RegExp().constructor.name

与所有 JavaScript 一样,有人最终总会指出这在某种程度上是邪恶的,所以这里有一个答案的链接,它很好地涵盖了这一点。

另一种方法是使用 Object.prototype.toString.call

Object.prototype.toString.call([])
Object.prototype.toString.call(/./)
由于确认怀疑在 javascript 中完成的所有事情在某种程度上是邪恶的,所以回答了。
2021-03-20 04:11:34
name 是 ECMAScript 的扩展,不适用于所有浏览器。
2021-03-30 04:11:34
邪恶:如果你正在缩小你的代码,那么constructor.name最终可能会出现类似的东西,n而不是你期望的对象名称。所以要注意这一点 - 特别是如果你只在生产中缩小。
2021-04-05 04:11:34
nullundefined不幸的是没有一个构造函数。
2021-04-05 04:11:34
JavaScript 本身就是邪恶的。而且很傻。这个问题没有好的答案这一事实就是活生生的证据。
2021-04-13 04:11:34

YUI3使用了一个相当不错的类型捕获函数

var TYPES = {
    'undefined'        : 'undefined',
    'number'           : 'number',
    'boolean'          : 'boolean',
    'string'           : 'string',
    '[object Function]': 'function',
    '[object RegExp]'  : 'regexp',
    '[object Array]'   : 'array',
    '[object Date]'    : 'date',
    '[object Error]'   : 'error'
},
TOSTRING = Object.prototype.toString;

function type(o) {
    return TYPES[typeof o] || TYPES[TOSTRING.call(o)] || (o ? 'object' : 'null');
};

这捕获了 javascript 提供的许多原语,但您始终可以通过修改TYPES对象来添加更多原语请注意,typeof HTMLElementCollection在 Safari 中将报告function,但 type(HTMLElementCollection) 将返回object

您可能会发现以下功能很有用:

function typeOf(obj) {
  return {}.toString.call(obj).split(' ')[1].slice(0, -1).toLowerCase();
}

或者在 ES7 中(如果有进一步改进请评论)

const { toString } = Object.prototype;

function typeOf(obj) {
  const stringified = obj::toString();
  const type = stringified.split(' ')[1].slice(0, -1);
      
  return type.toLowerCase();
}

结果:

typeOf(); //undefined
typeOf(null); //null
typeOf(NaN); //number
typeOf(5); //number
typeOf({}); //object
typeOf([]); //array
typeOf(''); //string
typeOf(function () {}); //function
typeOf(/a/) //regexp
typeOf(new Date()) //date
typeOf(new Error) //error
typeOf(Promise.resolve()) //promise
typeOf(function *() {}) //generatorfunction
typeOf(new WeakMap()) //weakmap
typeOf(new Map()) //map
typeOf(async function() {}) //asyncfunction

感谢@johnrees 通知我:错误、Promise、生成器函数

typeOf(Promise.resolve())//promise typeOf(function *() {})//generatorfunction
2021-03-18 04:11:34
不确定 TypeScript。你试过 ES7 版本吗?toString 没有被明确声明可能是原因?
2021-03-19 04:11:34
我无法在typescript中得到这个答案。给出错误:[ts] Cannot redeclare block-scoped variable 'toString'
2021-03-23 04:11:34
谢谢你。它也适用于日期对象:typeOf(new Date())
2021-04-11 04:11:34
啊,我忘记了 - 谢谢,现在已经包括在内。
2021-04-12 04:11:34

我们也可以从ipr101更改一个小例子

Object.prototype.toType = function() {
  return ({}).toString.call(this).match(/\s([a-zA-Z]+)/)[1].toLowerCase()
}

并称为

"aaa".toType(); // 'string'
记住孩子们,操作 JavaScript 基础对象会导致兼容性和其他奇怪的问题。尝试在库和大型项目中谨慎使用它!
2021-03-25 04:11:34