更好的方式来获得一个Javascriptvariables的types?
有没有更好的方式来获取JS中的variablestypes比typeof
? 它可以正常工作,当你这样做:
> typeof 1 "number" > typeof "hello" "string"
但是当你尝试的时候没用
> typeof [1,2] "object" >r = new RegExp(/./) /./ > typeof r "function"
我知道instanceof
,但是这需要你事先知道types。
> [1,2] instanceof Array true > r instanceof RegExp true
有没有更好的办法?
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() }
你可以尝试使用constructor.name
。
[].constructor.name new RegExp().constructor.name
就像所有JavaScript一样,最终总会有人指出这是某种邪恶的东西,所以这里有一个涵盖这个很好的答案的链接 。
另一种方法是使用Object.prototype.toString.call
Object.prototype.toString.call([]) Object.prototype.toString.call(/./)
YUI3使用的合适的types捕获函数是:
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
,但types(HTMLElementCollection)将返回object
您可能会发现以下function有用:
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
感谢@johnrees通知我:错误,承诺,发电机function
我们也可以从ipr101改变一个小例子
Object.prototype.toType = function() { return ({}).toString.call(this).match(/\s([a-zA-Z]+)/)[1].toLowerCase() }
并称之为
"aaa".toType(); // 'string'
一行function:
function type(obj) { return Object.prototype.toString.call(obj).replace(/^\[object (.+)\]$/,"$1").toLowerCase() }
这给出了与jQuery.type()
相同的结果
您可以将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除外 – 在从另一个窗口获得的variables上调用它时,它只会吐出[object Object]
。
我的2¢! 真的,我在这里抛出这个问题的部分原因,尽pipe答案很长,但是all in one
types的解决scheme中提供了更多的all in one
并且在将来如何扩展它以包含更多的real types
。
通过以下解决scheme,如前所述,我将这里find的几个解决scheme进行了组合,并在jQuery定义的对象( 如果可用)上join了一个返回jQuery值的修复程序 。 我也将该方法附加到本机对象原型。 我知道这往往是禁忌,因为它可能会干扰其他这样的扩展,但我留给user beware
。 如果你不喜欢这样做的话,只要简单地复制你喜欢的任何地方的基本函数,并用参数传入的参数(比如arguments [0])replace掉所有的variables。
;(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; })();
然后简单地使用,就像这样:
obj.realType() // would return 'Object' obj.realType(true) // would return 'object'
注意:有一个参数可以通过。 如果是
true
,那么返回将总是小写 。
更多示例:
true.realType(); // "Boolean" var a = 4; a.realType(); // "Number" $('div:first').realType(); // "jQuery" document.createElement('div').realType() // "HTMLDivElement"
如果你有什么需要补充的,比如定义一个对象是用另外一个库创build的(Moo,Proto,Yui,Dojo等等),请随意评论或编辑这个对象,并保持它的更多准确和精确。 或滚到我为它做的GitHub ,让我知道。 您还可以在那里find一个cdn min文件的快速链接。
function getType(obj) { if(obj && obj.constructor && obj.constructor.name) { return obj.constructor.name; } return Object.prototype.toString.call(obj).slice(8, -1).toLowerCase(); }
在我的初步testing中,这个工作非常好。 第一种情况将打印用“新”创build的任何对象的名称,第二种情况应该抓住一切。
我正在使用(8, -1)
因为我假定结果始终以[object
和end结束]
开头,但我不确定在每种情况下都是如此。