整理自 http://segmentfault.com/q/1010000000464600
在实际的项目应用中,typeof只有两个用途,就是检测一个元素是否为undefined,或者是否为function。
Value function typeof
-------------------------------------
"foo" String string
new String("foo") String object
1.2 Number number
new Number(1.2) Number object
true Boolean boolean
new Boolean(true) Boolean object
new Date() Date object
new Error() Error object
[1,2,3] Array object
new Array(1, 2, 3) Array object
new Function("") Function function
/abc/g RegExp object
new RegExp("meow") RegExp object
{} Object object
new Object() Object object
Object.prototype.toString()
有一个妙用,如果我们以某个特别的对象为上下文来调用该函数,它会返回正确的类型。我们需要做的就是手动处理其返回的字符串,最终便能获得typeof应该返回的正确字符串。
可以用来区分:Boolean
, Number
, String
, Function
, Array
, Date
, RegExp
, Object
, Error
等等。
公认的靠谱解法是 Object.prototype.toString.call(x) === '[object Array]'
关于如何区分『如何区分null,数组,和普通对象』
第一关 null
这一关最简单,有100%靠谱的简单解x === null
不多解释
第二关 []
x instanceof Array
看上去不错?可惜这不是最佳答案!问题在于window.Array
乃至[].constructor
都不100%靠谱,因为x可能来自另外一个frame!
公认的靠谱解法是
Object.prototype.toString.call(x) === '[object Array]'
第三关{}
x.constructor === Object
这个问题明显:怕{constructor:yyy}
但由于constructor这个名字在JS里的特殊地位,真有人乱用这个名字可以去打他的pp
try { var x2 = JSON.parse(JSON.stringify(x)); for(k in x) if(x2[k] !== x[k]) throw new Error() } catch(e) { return false; } return true;
好长……简单来说,就是可以被JSON化,又可以逆转回来保持信息不变,也就是判断对象是不是个JSON安全的普通意义上的数据对象
jQuery.isPlainObject
源码,通过各种检查努力排除了DOM,jQ,window对象,排除了绝大多数(并不100%)情况下new Xxx()
(Xxx非Object)出来的对象
后面这两个比较起来,前者不排斥但后者排斥的有function a(){}; new a()
(有自定义构造器),后者不排斥但前者排斥的有{aa:function(){}}
(JSON不安全的成员) var a = {}; a.me=a;
(循环引用)