JS框架设计之对象类型判断一种子模块

Javascript有两套数据类型,一套是基础数据类型,一套是对象数据类型。基础数据类型包括5种基本数据类型,分别是null,bool,undefined,number,string,也叫简单数据类型,object是复杂数据类型,其中Object,Array,Function属于引用类型(对象数据类型)。

基于这么多数据类型,所以JS就自带有类型判定的方法,typeof  用来检测基本数据类型,instanceof 用来检测对象数据类型,但是JS自带的这两套识别机制并不靠谱,所以产生了isXXX一系列来判断数据类型的方法,就拿typeof来说,他只能粗略的识别出string、number、boolean、function、undefined、object这6中数据类型,无法识别Null,RegExpAragument等细分对象类型

     /*
     Javascript有两套数据类型,一套是基础数据类型,一套是对象数据类型。基础数据类型包括5种基本数据类型,分别是null,bool,undefined,number,string,也叫简单数据类型,
     object是复杂数据类型,其中Object,Array,Function属于引用类型(对象数据类型)。基于这么多数据类型,所以JS就自带有类型判定的方法,typeof  用来检测基本数据类型,
     instanceof 用来检测对象数据类型,但是JS自带的这两套识别机制并不靠谱,所以产生了isXXX一系列来判断数据类型的方法,就拿typeof来说,
     他只能粗略的识别出string、number、boolean、function、undefined、object这6中数据类型,无法识别Null,RegExpAragument等细分对象类型
     */
    //下面就是自带的Js识别系统所带的坑

    console.log(typeof null);//输出:object
    console.log(typeof document.childNodes);//safari 输出:function
    console.log(document.createElement("embed"));//ff3-10  输出:function,其他浏览器都输出object
    console.log(document.createElement("object"));//ff3-10  输出:function,其他浏览器都输出object
    console.log(document.createElement("applet"));//ff3-10  输出:function,其他浏览器都输出object
    console.log(typeof /\d/i);//在实现了ecma262v4的浏览器上输出:function
    console.log(typeof window.alert);//IE678  输出:object, 其他浏览器输出:function
    //以上就是typeof的坑



    var iframe=document.createElement("iframe");
    document.body.appendChild(iframe);
    xArray=window.frames[window.frames.length-1].Array;
    var arr=new xArray(1,2,3);
    console.log(arr);//输出:1,2,3
    console.log(arr instanceof Array);//输出:false
    console.log(arr.constructor===Array);//输出:false
    //以上是instnceof的坑,只要原型上存在此对象的构造函数,那么就返回true,但是如果跨文档比较,iframe里面的数组实例就不是父窗口里面的Array的实例

    window.onload=function () {
        console.log(window.constructor);//IE67 undefined 其他object
        console.log(document.constructor);//IE67 undefined 其他object
        console.log(document.body.constructor);//IE67 undefined 其他object
        console.log((new ActiveXObject("Microsoft.XMLHttp")).constructor);//IE6789 undefined
    }
    //以上是constructor的坑,产生以上问题的原因是在旧版本IE下DOM和BOM是没有暴露出来的

     console.log(isNaN("aaa"));//输出:true
     console.log(isNaN(new Object()));//输出:true
    //isNaN这个方法非常不靠谱,当我们传入字符串和对象时,输出也是true,这对我们的序列化是非常不利的


    if(typeof window.ActiveXObject!="undefined")
    {
        var  xhr=new ActiveXObject("Msxml2.XMLHTTP");
        console.log(typeof xhr.abort);//输出:unknown
    }
    //以上是在IE下的typeof返回unknown的情况

    /*
    之前大多数人用document.all是否存在来判定IE,因为用document.all来取得页面中的元素是不错的注意,但是这个方法其他浏览器也觊觎了好久,
    于是就有了Chrome下的闹剧
     */
    console.log(typeof document.all); //IE78中输出:object,在Chrome中输出:undefined
    console.log(document.all);//在Chrome中,虽然typeof输出的是:undefined,但是document.all却能获取到所有的网页元素,输出:HTMLAllCollection[6]
   /*
    以下是jQuery判断js数据类型的方法$.type
     */
    var jQuery={};
    var class2Type={};
    var dataType=["Boolean","Number","String","Function","Array","Date","RegExpObject","Function"];
    for(var i=0;i<dataType.length;i++)
    {
        class2Type["[object "+dataType[i]+"]"]=dataType[i].toLowerCase();
    }
    jQuery.type=function (obj) {
        return obj==null?obj+"":class2Type[Object.prototype.toString.call(obj)] || "object";
    }

    var aa=false;
    function bb(){}
    alert(Object.prototype.toString.call(aa))//输出:[object Number]
    alert(jQuery.type(bb))//输出:number
    var mass={};
    var class2Type={
        "[objectHTMLDocument]":"Document",
        "[objectHTMLCollection]":"NodeList",
        "[objectStaticNodeList]":"NodeList",
        "[obejctIXMLDOMNodeList]":"NodeList",
        "[objectDOMWindow]":"Window",
        "null":"Null",
        "NaN":"NaN",
        "undefined":"Undefined"
    }
    var toString=class2Type.toString;
    var AllDataType=["Boolean","Number","String","Function","Array","Date","RegExp","Error","Symbol","Arguements","Window","Document"];
    //填充class2Type集合用于判断js数据类型,通过Object.prototype.toString.call()来判断解决typeof和instanceof"不靠谱"的问题
    //class2Type这个映射几乎将所有的对象类型一网打尽
    for(var i=0;i<AllDataType.length;i++)
    {
        class2Type["[object "+AllDataType[i]+"]"]=AllDataType[i];
    }
    mass.type=function (obj,str) {
        //1、当传入的对象不等于null或者自己的类型不等于自己的时候,直接去class2Type中找自己的类型,
        // 2、如果找不到做Object.prototype.toString转换,再去class2type中找
        //3、如果在class2type中找不到类型,那么找传入对象的nodeName(传入的参数可能是html元素节点)
        //4、如果上面的条件都不满足那么就把result设为"#"
        var result=class2Type[(obj==null || obj!==obj?obj:toString.call(obj))] || obj.nodeName || "#";
        //兼容旧版本浏览器处理个别情况,如window,opera
        //利用IE678中window==document为true,document==window为false的神奇特性
        if(result.charAt(0)=="#")
        {
            if(obj==obj.document && obj.document!=obj)
            {
                result="Window";
            }
            else if(obj.nodeType===9)
            {
                result="Document";
            }
            else if(obj.callee)
            {
                result="Arguements";
            }
            else if(isFinite(obj.length) && obj.item)
            {
                result="NodeList";
            }else
            {
                result=toString.call(obj).slice(8,-1);
            }
        }
        if(str)
        {
            return str===result;
        }
        return result;
    }
    //type方法直接用toString.call(obj)做键,直接从事先存好的映射中取出。只有在IE6、IE7、IE8中才废一些周折处理window、document
    //Arguement、nodeList等模块

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Golang语言社区

GO语言标准错误处理机制error用法实例

本文实例讲述了GO语言标准错误处理机制error用法。分享给大家供大家参考。具体分析如下: 在 Golang 中,错误处理机制一般是函数返回时使用的,是对外的接...

3449
来自专栏Golang语言社区

Golang指针与nil浅析

曾经听说过一句话,编程的本质就是指针和递归。那会刚开始编码,只是这两个的概念有个感性粗浅的认识。最早接触指针,莫过于C语言了,能否理解用好指针也成为一个合格C语...

3006
来自专栏编程

从零开始学正则

问题:我怎么才能收到你们公众号平台的推送文章呢? 正则规范 正则表达式的英文是regular expression简称regex。正则表达式就是用事先定义好的一...

1928
来自专栏SeanCheney的专栏

Python基础回顾基本数据类型和运算容器分支和循环函数、生成器和类map, reduce和filter列表生成(list comprehension)字符串文件操作和pickle异常多进程(mult

Python shell输入import this 可以看到The Zen of Python 基本数据类型和运算 基本数据类型 Python中最基本的数据类...

4807
来自专栏Golang语言社区

Go语言基本语法

前面已经看到了Go程序的基本结构,所以这将是很容易理解Go编程语言等基本构建块。 Go令牌 Go程序包括各种令牌和令牌可以是一个关键字,一个标识符,常量,字符串...

2826
来自专栏超然的博客

ECMAScript 6 笔记(六)

  在let和const之间,建议优先使用const,尤其是在全局环境,不应该设置变量,只应设置常量。

651
来自专栏数据结构与算法

计算(calc.cpp)

计算(calc.cpp) 【问题描述】 小明在你的帮助下,破密了Ferrari设的密码门,正要往前走,突然又出现了一个密码门,门上有一个算式,其中只有“(”,“...

39910
来自专栏web前端-

JavaScript基础概述

    1.常量: 常量就是在程序运行过程中,不会发生变化的量,常量通常用来表示固定不变的量,比如圆周率,万有引力常量

762
来自专栏小詹同学

Python系列之——字符串格式化(xiaozhan is a boy of 22 years old.)

不知道小伙伴有没有遇到过字符串输出有格式要求的情况呢?今天小詹学习分享一波python的字符串格式化的方法。学以致用,首先我们得明确为什么要格式化字符串输出,以...

712
来自专栏Web 开发

JavaScript的对象引用

在一个函数体内,var变量声明的变量,其作用域只在该函数体内,对于函数体外而言,是不可见的(废话)。

840

扫码关注云+社区

领取腾讯云代金券