获取 Javascript 变量类型的更好方法?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7390426/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Better way to get type of a Javascript variable?
提问by Aillyn
Is there a better way to get the type of a variable in JS than typeof
? It works fine when you do:
有没有比 JS 更好的方法来获取变量的类型typeof
?当你这样做时它工作正常:
> typeof 1
"number"
> typeof "hello"
"string"
But it's useless when you try:
但是当你尝试时它是没用的:
> typeof [1,2]
"object"
>r = new RegExp(/./)
/./
> typeof r
"function"
I know of instanceof
, but this requires you to know the type beforehand.
我知道instanceof
,但这需要您事先知道类型。
> [1,2] instanceof Array
true
> r instanceof RegExp
true
Is there a better way?
有没有更好的办法?
采纳答案by ipr101
Angus Croll recently wrote an interesting blog post about this -
Angus Croll 最近写了一篇关于这个的有趣的博客文章 -
http://javascriptweblog.wordpress.com/2011/08/08/fixing-the-javascript-typeof-operator/
http://javascriptweblog.wordpress.com/2011/08/08/fixing-the-javascript-typeof-operator/
He goes through the pros and cons of the various methods then defines a new method 'toType' -
他分析了各种方法的优缺点,然后定义了一个新方法“toType”——
var toType = function(obj) {
return ({}).toString.call(obj).match(/\s([a-zA-Z]+)/)[1].toLowerCase()
}
回答by Alex Turpin
You can try using constructor.name
.
您可以尝试使用constructor.name
.
[].constructor.name
new RegExp().constructor.name
As with everything JavaScript, someone will eventually invariably point that this is somehow evil, so here is a link to an answerthat covers this pretty well.
与所有 JavaScript 一样,有人最终总会指出这在某种程度上是邪恶的,所以这里有一个答案的链接,它很好地涵盖了这一点。
An alternative is to use Object.prototype.toString.call
另一种方法是使用 Object.prototype.toString.call
Object.prototype.toString.call([])
Object.prototype.toString.call(/./)
回答by Nick Husher
A reasonably good type capture function is the one used by YUI3:
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');
};
This captures many of the primitives provided by javascript, but you can always add more by modifying the TYPES
object. Note that typeof HTMLElementCollection
in Safari will report function
, but type(HTMLElementCollection) will return object
这捕获了 javascript 提供的许多原语,但您始终可以通过修改TYPES
对象来添加更多原语。请注意,typeof HTMLElementCollection
在 Safari 中将报告function
,但 type(HTMLElementCollection) 将返回object
回答by Vix
You may find the following function useful:
您可能会发现以下功能很有用:
function typeOf(obj) {
return {}.toString.call(obj).split(' ')[1].slice(0, -1).toLowerCase();
}
Or in ES7 (comment if further improvements)
或者在 ES7 中(如果有进一步改进请评论)
function typeOf(obj) {
const { toString } = Object.prototype;
const stringified = obj::toString();
const type = stringified.split(' ')[1].slice(0, -1);
return type.toLowerCase();
}
Results:
结果:
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
Thanks @johnrees for notifying me of: error, promise, generatorfunction
感谢@johnrees 通知我:错误、承诺、生成器函数
回答by greymaster
Also we can change a little example from ipr101
我们也可以从ipr101更改一个小例子
Object.prototype.toType = function() {
return ({}).toString.call(this).match(/\s([a-zA-Z]+)/)[1].toLowerCase()
}
and call as
并称为
"aaa".toType(); // 'string'
回答by Yukulélé
one line function:
一行功能:
function type(obj) {
return Object.prototype.toString.call(obj).replace(/^\[object (.+)\]$/,"").toLowerCase()
}
this give the same result as jQuery.type()
这给出了相同的结果 jQuery.type()
回答by Andy E
You can apply Object.prototype.toString
to any object:
您可以应用于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]
This works well in all browsers, with the exception of IE - when calling this on a variable obtained from another window it will just spit out [object Object]
.
这适用于所有浏览器,IE 除外 - 当在从另一个窗口获得的变量上调用它时,它只会吐出[object Object]
.
回答by SpYk3HH
My 2¢!Really, part of the reason I'm throwing this up here, despite the long list of answers, is to provide a little more all in one
type solution and get some feed back in the future on how to expand it to include more real types
.
我的2¢!真的,尽管有很长的答案列表,但我在这里抛出这个问题的部分原因是提供更多all in one
类型的解决方案,并在未来获得一些关于如何扩展它以包含更多real types
.
With the following solution, as aforementioned, I combined a couple of solutions found here, as well as incorporate a fixfor returning a value of jQueryon jQuery defined object if available. I also append the method to the native Object prototype. I know that is often taboo, as it could interfere with other such extensions, but I leave that to user beware
. If you don't like this way of doing it, simply copy the base function anywhere you like and replace all variables of this
with an argument parameter to pass in (such as arguments[0]).
使用以下解决方案,如前所述,我结合了此处找到的几个解决方案,并合并了一个修复程序,用于返回jQueryjQuery 定义的对象(如果可用)的值。我还将该方法附加到本机 Object 原型。我知道这通常是禁忌,因为它可能会干扰其他此类扩展,但我将其留给user beware
. 如果您不喜欢这种方式,只需将基本函数复制到您喜欢的任何位置,并将所有变量替换为this
要传入的实参参数(例如arguments[0])。
;(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;
})();
Then simply use with ease, like so:
然后简单地使用,像这样:
obj.realType() // would return 'Object'
obj.realType(true) // would return 'object'
Note:There is 1 argument passable. If is bool of
true
, then the return will always be in lowercase.
注意:有 1 个参数可以通过。如果是 bool of
true
,则返回将始终为小写。
More Examples:
更多例子:
true.realType(); // "Boolean"
var a = 4; a.realType(); // "Number"
$('div:first').realType(); // "jQuery"
document.createElement('div').realType() // "HTMLDivElement"
If you have anything to add that maybe helpful, such as defining when an object was created with another library (Moo, Proto, Yui, Dojo, etc...) please feel free to comment or edit this and keep it going to be more accurate and precise. OR roll on over to the GitHubI made for it and let me know. You'll also find a quick link to a cdn min file there.
如果您有任何可能有帮助的要添加的内容,例如定义何时使用另一个库(Moo、Proto、Yui、Dojo 等)创建对象,请随时发表评论或编辑此内容并保持更多准确和精确。或者翻到GitHub我为它做的,让我知道。您还可以在那里找到指向 cdn min 文件的快速链接。
回答by Arsenowitch
I guess the most universal solution here - is to check for undefined
and null
first, then just call constructor.name.toLowerCase()
.
我想这里最通用的解决方案是检查undefined
和null
首先,然后调用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'
回答by mpen
function getType(obj) {
if(obj && obj.constructor && obj.constructor.name) {
return obj.constructor.name;
}
return Object.prototype.toString.call(obj).slice(8, -1).toLowerCase();
}
In my preliminary tests, this is working pretty well. The first case will print the name of any object created with "new", and the 2nd case should catch everything else.
在我的初步测试中,这工作得很好。第一种情况将打印使用“new”创建的任何对象的名称,第二种情况应捕获其他所有内容。
I'm using (8, -1)
because I'm assuming that the result is always going to start with [object
and end with ]
but I'm not certain that's true in every scenario.
我使用(8, -1)
是因为我假设结果总是以开始[object
和结束,]
但我不确定在每种情况下都是如此。