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

时间:2011-09-12 15:39:10

标签: javascript types typeof

是否有更好的方法来获取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

有更好的方法吗?

13 个答案:

答案 0 :(得分:205)

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()
}

答案 1 :(得分:46)

您可以尝试使用constructor.name

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

与所有JavaScript一样,有人最终会指出这是某种邪恶,所以here is a link to an answer很好地涵盖了这一点。

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

Object.prototype.toString.call([])
Object.prototype.toString.call(/./)

答案 2 :(得分:38)

一个相当不错的类型捕获函数是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对象来添加更多基元。请注意,Safari中的typeof HTMLElementCollection将报告function,但类型(HTMLElementCollection)将返回object

答案 3 :(得分:25)

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

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

或在ES7中(如果进一步改进则发表评论)

function typeOf(obj) {
  const { toString } = Object.prototype;
  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

感谢@johnrees通知我:错误,承诺,生成器功能

答案 4 :(得分:14)

我们也可以从 ipr101

改变一个小例子
Object.prototype.toType = function() {
  return ({}).toString.call(this).match(/\s([a-zA-Z]+)/)[1].toLowerCase()
}

并致电

"aaa".toType(); // 'string'

答案 5 :(得分:8)

一行函数:

function type(obj) {
    return Object.prototype.toString.call(obj).replace(/^\[object (.+)\]$/,"$1").toLowerCase()
}

这与jQuery.type()

的结果相同

答案 6 :(得分:3)

您可以将Object.prototype.toString应用于任何对象:

var toString = Object.prototype.toString;

console.log(toString.call([]));
//-> [object Array]

console.log(toString.call(/reg/g));
//-> [object RegExp]

console.log(toString.call({}));
//-> [object Object]

这适用于所有浏览器,IE除外 - 当从另一个窗口获取的变量上调用它时,它只会吐出[object Object]

答案 7 :(得分:3)

我的2¢!真的,我把这个放在这里的部分原因,尽管有很长的答案清单,是为了提供更多 {{1 }} 输入解决方案并在将来获取一些反馈,了解如何扩展它以包含更多 all in one

通过以下解决方案,如上所述,我结合了这里找到的几个解决方案,并在定义的对象中包含 fix 以返回值jQuery 如果可用 。我还将该方法附加到本机Object原型。我知道这通常是禁忌,因为它可能会干扰其他此类扩展,但我将其留给 real types 。如果您不喜欢这种方式,只需将基函数复制到您喜欢的任何位置,并用参数参数替换user beware的所有变量以传入(例如arguments [0])。

this

然后简单地使用,就像这样:

;(function() {  //  Object.realType
    function realType(toLower) {
        var r = typeof this;
        try {
            if (window.hasOwnProperty('jQuery') && this.constructor && this.constructor == jQuery) r = 'jQuery';
            else r = this.constructor && this.constructor.name ? this.constructor.name : Object.prototype.toString.call(this).slice(8, -1);
        }
        catch(e) { if (this['toString']) r = this.toString().slice(8, -1); }
        return !toLower ? r : r.toLowerCase();
    }
    Object['defineProperty'] && !Object.prototype.hasOwnProperty('realType')
        ? Object.defineProperty(Object.prototype, 'realType', { value: realType }) : Object.prototype['realType'] = realType;
})();
  

注意:有1个参数可通过。如果是obj.realType() // would return 'Object' obj.realType(true) // would return 'object' 的bool,则返回将始终为小写

更多例子:

true

如果您要添加任何可能有用的内容,例如定义何时使用其他库(Moo,Proto,Yui,Dojo等等)创建对象,请随时评论或编辑此内容并继续使用更准确和准确。或者滚动到我为它制作的GitHub并告诉我。你还可以找到一个快速链接到那里的cdn min文件。

答案 8 :(得分:2)

function getType(obj) {
    if(obj && obj.constructor && obj.constructor.name) {
        return obj.constructor.name;
    }
    return Object.prototype.toString.call(obj).slice(8, -1).toLowerCase();
}

在我的初步测试中,这非常有效。第一种情况将打印使用" new"创建的任何对象的名称,第二种情况应该捕获其他所有内容。

我正在使用(8, -1),因为我假设结果始终以[object开头,以]结尾,但我不是确定在每种情况下都是如此。

答案 9 :(得分:0)

我想这里最通用的解决方案是先检查undefinednull,然后再调用constructor.name.toLowerCase()

const getType = v =>
  v === undefined
    ? 'undefined'
    : v === null
      ? 'null'
      : v.constructor.name.toLowerCase();




console.log(getType(undefined)); // 'undefined'
console.log(getType(null)); // 'null'
console.log(getType('')); // 'string'
console.log(getType([])); // 'array'
console.log(getType({})); // 'object'
console.log(getType(new Set())); // `set'
console.log(getType(Promise.resolve())); // `promise'
console.log(getType(new Map())); // `map'

答案 10 :(得分:0)

typeof条件用于检查变量类型,如果您在if-else条件下检查变量类型 例如

if(typeof Varaible_Name "undefined")
{

}

答案 11 :(得分:0)

此版本是更完整的版本:

const typeOf = obj => {
  let type = ({}).toString.call(obj).match(/\s([a-zA-Z]+)/)[1]
  if (type === 'Object') {
    const results = (/^(function|class)\s+(\w+)/).exec(obj.constructor.toString())
    type = (results && results.length > 2) ? results[2] : ''
  }
  return type.toLowerCase()
}

现在您不仅可以得到以下结果:(如此处已回答)

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

但是您也可以从类或函数中获取构造的每个实例或对象的类型:(在其他答案之间无效,它们都返回对象)

class C {
  constructor() {
    this.a = 1
  }
}

function F() {
  this.b = 'Foad'
}

typeOf(new C()) // -> c
typeOf(new F()) // -> f

答案 12 :(得分:-1)

我做了这个功能:

(您应该将其命名为更独特的,以免与其他一些全局名称冲突。)

function type(theThing) {
    return Object.prototype.toString.call(theThing).match(/\s([\w]+)/)[1].toLowerCase()
}

type({})           //-> 'object'
type([])           //-> 'array'
type(function(){}) //-> 'function'

type(null)         //-> 'null'
type(undefined)    //-> 'undefined

type(Symbol())     //-> 'symbol'
type(true)         //-> 'boolean'
type('hello')      //-> 'string'
type(42)           //-> 'number'