javascript有数组,对象,函数,字符串,布尔,还有Symbol,set,map,weakset,weakmap。
判断这些东西也是有很多坑,像原生的typeof,instanceOf有一些bug,有些能满足90%的情况,也有些不太如人意。
所以各大类库都出了一些判断的函数,以is开头的xxx。
1,判断null
typeof null//'object',所以不能用typeof判断。typeof的一个坑。
null大家都是用 null===null判断的。jquery阿underscore都是这么写:
function isNull(obj){return obj===null}
2.undefined
typeof undefined==="undefined",还不能直接写undefined,而jq等类库和underscore都是这么写的:
function isUndefined(obj){return obj===void 0;}
3.NaN
typeof NaN==="number",js内置的isNaN在输入字符串,对象都返回true,白瞎这个名字了,不过倒是有人用这个判断数字,!isNaN(number)。所以判断NaN的时候是:
function isNaN(obj){return obj!==obj}
jquery,underscore等类库也都是这么判断,看来大家意见差不多。
3.window对象
jquery的判断window对象
//判断window function isWindow(){ window==document//IE678 true document==window//IE678 false }
3.判断基础类型Number,boolean,function,string。
//typeof判断string,number,boolean,function可满足90%的需求 //但是。。。 typeof new Boolean(1);//"object" typeof new Number(1);//"object" typeof new String(1);//"object"
这些要判断也蛮简单的,上一下underscore的源码吧。
_.isFunction / _.isString / _.isNumber / _.isDate / _.isRegExp都是这样。。用Object.prototype.toString.call(obj)判断
刚刚试了下,Object.toString.call和原型链上的toString返回的不一样-0-。
_.isFunction = function(obj) { return Object.protorype.toString.call(obj) == '[object Function]'; };
underscore的boolean的判断还是蛮全的,包括字面量,对象形式的boolean:
_.isBoolean = function(obj) { return obj === true || obj === false || toString.call(obj) == '[object Boolean]'; };
4.object
typeof 太多东西都是object了,看看underscore咋判断
_.isObject = function(obj) { return obj === Object(obj); };
//这里 typeof null//'object' typeof []//object typeof /\d/i //"object" typeof window.alert //IE678 "object"
5.element
_.isElement = function(obj) { return !!(obj && obj.nodeType == 1); };
6.Arguments
这是underscore的判断Arguments,和源码,注释很清楚也不多说。
_.isArguments = function(obj) { return toString.call(obj) == '[object Arguments]'; }; // 验证isArguments函数, 如果运行环境无法正常验证arguments类型的数据, 则重新定义isArguments方法 if(!_.isArguments(arguments)) { // 对于环境无法通过toString验证arguments类型的, 则通过调用arguments独有的callee方法来进行验证 _.isArguments = function(obj) { // callee是arguments的一个属性, 指向对arguments所属函数自身的引用 return !!(obj && _.has(obj, 'callee')); }; }
7.Array
判断数组是最麻烦的,前面的还好,数组默认的0,1,2,3的下标,一个length属性,一些Array方法,判断的时候还要保证obj不是类数组,还要保证不是Arguments。。
我们看一下这些类库探索Array的路程
开始是
return arr.instanceof Array;
后来
return !!arr&&arr.constructor==Array;
return typeof arr.sort=='function'
return try{ Array.prototype.toString.call(o); return true; }catch(e){ return false; }
从instanceof判断,constructor的判断到Array的toString方法的判断,可谓是用尽心思,最新版的jquery的判断array好像把这好多方法集合在一起,写的老长。
underscore的判断还是用它的toString.call判断:
_.isArray = nativeIsArray || function(obj) { return toString.call(obj) == '[object Array]'; };
如果js原生支持isArray就先用原生的,这个nativeIsArray在一开始被设置为Array的isArray方法。
各大框架也有类数组的判断,这个更麻烦,老长的代码,判断原理是类数组的length属性能被重写,而数组的length属性不能被重新,代码就不贴了。
8.iframe
//判断页面是否在iframe function(){ alert(window!=window.top) alert(window.frameElement!==null) alert(window.eval!==top.eval) }
//判断iframe与父页面同源 function isSameOrigin(el){ var ret=false; try{ ret=!!el.contentWindow.location.href; }catch(e){} return ret; }
附赠取iframe的函数
//取iframe的对象 function getIframeDocument(node){ return node.contentDocument||node.contentWindow.document }
总结一下原生判断的一些坑。
//typeof 的陷阱 typeof null//'object' typeof []//object typeof document.childNodes //safari "function" typeof document.createElement('embed')//ff3-10 "function" typeof document.createElement('object')//ff3-10 "function" typeof document.createElement('applet')//ff3-10 "function" typeof /\d/i typeof window.alert //IE678 "object" //instanceof不能跨文档比较 iframe里面的数组实例不是父窗口的Array实例 instanceof //contructor的陷阱 //旧版本ie下dom bom对象的constructor属性没有暴露出来
好,今天就写这么多,谢谢观看,如有错误,请指出,大家共同学习~