zoukankan      html  css  js  c++  java
  • javascript类型判断

    题目:

    请在index.html文件中,编写arraysSimilar函数,实现判断传入的两个数组是否相似。具体需求:

    1. 数组中的成员类型相同,顺序可以不同。例如[1, true] 与 [false, 2]是相似的。

    2. 数组的长度一致。

    3. 类型的判断范围,需要区分:String, Boolean, Number, undefined, null, 函数,日期, window.

    当以上全部满足,则返回"判定结果:通过",否则返回"判定结果:不通过"。

    一、测试用例

    var result=function(){
        //以下为多组测试数据
                var cases=[{
                        arr1:[1,true,null],
                        arr2:[null,false,100],
                        expect:true
                    },{
                        arr1:[function(){},100],
                        arr2:[100,{}],
                        expect:false
                    },{
                        arr1:[null,999],
                        arr2:[{},444],
                        expect:false
                    },{
                        arr1:[window,1,true,new Date(),"hahaha",(function(){}),undefined],
                        arr2:[undefined,(function(){}),"okokok",new Date(),false,2,window],
                        expect:true
                    },{
                        arr1:[new Date()],
                        arr2:[{}],
                        expect:false
                    },{
                        arr1:[window],
                        arr2:[{}],
                        expect:false
                    },{
                        arr1:[undefined,1],
                        arr2:[null,2],
                        expect:false
                    },{
                        arr1:[new Object,new Object,new Object],
                        arr2:[{},{},null],
                        expect:false
                    },{
                        arr1:null,
                        arr2:null,
                        expect:false
                    },{
                        arr1:[],
                        arr2:undefined,
                        expect:false
                    },{
                        arr1:"abc",
                        arr2:"cba",
                        expect:false
                    }];
                
        //使用for循环, 通过arraysSimilar函数验证以上数据是否相似,如相似显示“通过”,否则"不通过",所以大家要完成arraysSimilar函数,具体要求,详见任务要求。    
                for(var i=0;i<cases.length;i++){
                    if(arraysSimilar(cases[i].arr1,cases[i].arr2)!==cases[i].expect) {
                        document.write("不通过!case"+(i+1)+"不正确!arr1="+JSON.stringify(cases[i].arr1)+", arr2="+JSON.stringify(cases[i].arr2)+" 的判断结果不是"+cases[i].expect);
                        return false;
                    }                
                }
                return true;
                
            }();
        document.write("判定结果:"+(result?"通过":"不通过"));

    这个文件为testData.js。主要任务是完成arraysSimilar函数。

    二、arraySimilar函数

    1、我的写法

    1、判断2个参数是否都是数组,不是就返回false;

    2、判断2个数组长度是否一致,不是直接返回fasle;

    3、新建2个临时数组temp1,temp2并初始化为0,用来存放arr1和arr2中各种类型的个数。

    var temp1 = [0, 0, 0, 0, 0, 0, 0, 0];
    var temp2 = [0, 0, 0, 0, 0, 0, 0, 0];

    4、遍历2个arr1和arr2,每遍历一个元素,将对应类型加1。

    5、完成arr1和arr2的遍历后,通过temp1.toString()和temp2.toString()是否相等得出2个数组是否相似。

    <!DOCTYPE HTML>
    <html>
    <meta charset="utf-8">
    
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=gb18030">
        <title>Untitled Document</title>
    </head>
    
    <body>
        <script type="text/javascript">
        /*
         * param1 Array 
         * param2 Array
         * return true or false
         */
        function arraysSimilar(arr1, arr2) {
            console.log("arr1为" + arr1);
            console.log("arr2为" + arr2);
    
            if (!(arr1 instanceof Array) || !(arr2 instanceof Array)) {
                document.write(false + "<br/>");
                return false;
            } else if (arr1.length != arr2.length) {
                document.write(false + "<br/>");
                return false;
            }
            var temp1 = [0, 0, 0, 0, 0, 0, 0, 0];
            var temp2 = [0, 0, 0, 0, 0, 0, 0, 0];
            //初始化temp1
            for (i = 0; i < arr1.length; i++) {
                console.log("arr1的第" + i + "个值为" + arr1[i]);
                switch (jsType(arr1[i])) {
                    case "String":
                        temp1[0]++;
                        break;
                    case "Boolean":
                        temp1[1]++;
                        break;
                    case "Number":
                        temp1[2]++;
                        break;
                    case "Undefined":
                        temp1[3]++;
                        break;
                    case "Null":
                        temp1[4]++;
                        break;
                    case "Function":
                        temp1[5]++;
                        break;
                    case "Date":
                        temp1[6]++;
                        break;
                    case "Window":
                        temp1[7]++;
                        break;
                }
                console.log("arr2的第" + i + "个值为" + arr2[i]);
                //初始化temp2
                switch (jsType(arr2[i])) {
                    case "String":
                        temp2[0]++;
                        break;
                    case "Boolean":
                        temp2[1]++;
                        break;
                    case "Number":
                        temp2[2]++;
                        break;
                    case "Undefined":
                        temp2[3]++;
                        break;
                    case "Null":
                        temp2[4]++;
                        break;
                    case "Function":
                        temp2[5]++;
                        break;
                    case "Date":
                        temp2[6]++;
                        break;
                    case "Window":
                        temp2[7]++;
                        break;
                }
            }
            //判断temp1和temp2是否相等
            if (temp1.toString() === temp2.toString()) {
                document.write(true + "<br/>");
                return true;
            } else {
                document.write(false + "<br/>");
                return false;
            }
    
    
        }
        //返回参数的javascript类型
        function jsType(arg) {
            //判断字符串
            if (typeof arg == "string") {
                console.log("string");
                return "String";
            }
            //判断Boolean
            if (typeof arg == "boolean") {
                console.log("boolean");
                return "Boolean";
            }
            //判断Number
            if (typeof arg == "number") {
                console.log("Number");
                return "Number";
            }
            //判断Undefined
            if (typeof arg == "undefined") {
                console.log("Undefined");
                return "Undefined";
            }
            //判断Null(不考虑IE8以下) //看了答案发现直接=== null判断就好了
            if (Object.prototype.toString.apply(arg) == "[object Null]") {
                console.log("Null");
                return "Null";
            }
            //判断Function
            if (typeof arg == "function") {
                console.log("Function");
                return "Function";
            }
            //判断日期
            if (arg instanceof Date) {
                console.log("Date");
                return "Date";
            }
            //判断window     //看了答案发现直接=== window 判断就好了
            if (arg instanceof Window) {
                console.log("window");
                return "Window";
            }
        }
        </script>
        <script src="testData.js"></script>
    </body>
    
    </html>

    虽然代码略粗糙,但是功能完成了。网上看了其他人的答案确实不同的人做法不一样,有些值得借鉴的地方。

    2、其他答案

    建一个类型对象数组obj,初始化为零,arr1遍历时每个元素对应的类型加一,arr2遍历时每个元素对应的类型减一,最终判断obj里所有键的值都为0即相似数组。

    function check(i){
            //除了function 其他的引用类型用instanceof来判定
            if(i instanceof Date){
                return 'date';
            }
            else if(i instanceof Window){
                return 'window';
            }
           // typeof可以判断基本类型(number string boolean null(typeof 返回object) undefined )和引用类型的function类型
            if(typeof i === 'number')return 'number';
            else if(typeof i === 'string')return 'string';
            else if(typeof i === 'boolean')return 'boolean';
            else if(typeof i === 'function')return 'function';
            //typeof null 返回 object
            else if(typeof i === 'object'){
                if(i === null){
                    return 'null';
                }else{
                    return 'object';
                }
            }
            else if(typeof i === 'undefined'){
                return 'undefined';
            }
        }
        function arraysSimilar(arr1, arr2){
            if(!arr1||!arr2){return false;}
            if(!(arr1 instanceof Array )||!(arr2 instanceof Array))return false;
            if(arr1.length!=arr2.length)return false;
            var obj={
                'number':0,
                'string':0,
                'boolean':0,
                'undefined':0,
                'null':0,
                'function':0,
                'date':0,
                'object':0,
                'window':0
                    };
            for(var i=0;i<arr1.length;i++){
    
                var r1=check(arr1[i]);
                var r2=check(arr2[i]);
                obj[r1]++;
                obj[r2]--;
            }
            for(var o in obj){
                if(obj[o]!=0)return false;
            }
            return true;
    
        }

    还有一个答案,差不多算标准答案,当然这种题也没有标准答案。和上个答案的差别是,用map(在js中也就是对象)存放数据类型和次数,这个map初始化为{},在后面动态生成的。

    /**
     * String, Boolean, Number, undefined, null, 函数,日期, window
     */
    function arraysSimilar(arr1, arr2) {
        // 判断参数,确保arr1, arr2是数组,若不是直接返回false
        if (!(arr1 instanceof Array)
            || !(arr2 instanceof Array)) {
            return false;
        }
     
        // 判断长度
        if (arr1.length !== arr2.length) return false;
     
        var i = 0, 
            n = arr1.length, 
            countMap1 = {},  // 用来计算数组元素数据类型个数的map,key是TYPES中的类型字符串,value是数字表示出现次数。
            countMap2 = {},
            t1, t2,
            TYPES = ['string', 'boolean', 'number', 'undefined', 'null',
                'function', 'date', 'window'];
     
        // 因为是无序的,用一个对象来存储处理过程。key为类型, value为该类型出现的次数。
        // 最后校验:若每一种数据类型出现的次数都相同(或都不存在),则证明同构。
        for (; i < n; i++) {
            t1 = typeOf(arr1[i]);
            t2 = typeOf(arr2[i]);
            if (countMap1[t1]) {
                countMap1[t1]++;
            } else {
                countMap1[t1] = 1;
            }
            if (countMap2[t2]) {
                countMap2[t2]++;
            } else {
                countMap2[t2] = 1;
            }
        }
     
        // 因为typeof只能判断原始类型,且无法判断null(返回"object"),所以自己写typeof方法扩展。
        function typeOf(ele) {
            var r;
            if (ele === null) r = 'null'; // 判断null
            else if (ele instanceof Array) r = 'array';  // 判断数组对象
            else if (ele === window) r = 'window';  // 判断window
            else if (ele instanceof Date) r = 'date'  // 判断Date对象
            else r = typeof ele; // 其它的,使用typeof判断
            return r;
        }
     
        for (i = 0, n = TYPES.length; i < n; i++) {
            if (countMap1[TYPES[i]] !== countMap2[TYPES[i]]) {
                return false;
            }
        }
     
        return true;
    }

    还有一个比较简洁也好理解的解法

    <script type="text/javascript">   
            /*
             * param1 Array 
             * param2 Array
             * return true or false
             */
            function type(a){
                return  a === null ? '[object Null]':Object.prototype.toString.apply(a); //hack ie678
            }
            function arraysSimilar(arr1, arr2){
                if(!Array.isArray(arr1) || !Array.isArray(arr2) ||arr1.length!=arr2.length){return false;}
                var arr3=[];
                var arr4=[];
                var x;
                for(var i in arr1){
                    arr3.push(type(arr1[i]));
                    arr4.push(type(arr2[i]));
                }
                if(arr3.sort().toString()==arr4.sort().toString()){
                    return true;
                }else{
                    return false;
                }
            }
        </script>

    还有一个精妙的解法,我对这种不感兴趣,没仔细看。

    var global = window;
    function arraysSimilar(arr1, arr2){
        return (arr1 instanceof Array && arr2 instanceof Array) && JSON.stringify(arr1.map(function(v) {
            return null === v ? "☀" : (v instanceof Date ? "❤" : (v === global ? "❀" : typeof v));
        }).sort()) === JSON.stringify(arr2.map(function(v) {
            return null === v ? "☀" : (v instanceof Date ? "❤" : (v === global ? "❀" : typeof v));
        }).sort());
    }

    参考:http://www.imooc.com/qadetail/62836

     本文作者starof,因知识本身在变化,作者也在不断学习成长,文章内容也不定时更新,为避免误导读者,方便追根溯源,请诸位转载注明出处:http://www.cnblogs.com/starof/p/4904929.html有问题欢迎与我讨论,共同进步。

  • 相关阅读:
    【leetcode】二叉搜索树的最近公共祖先
    052-12
    052-11
    052-10
    052-9
    052-8
    052-6
    052-5
    052-3
    052-2
  • 原文地址:https://www.cnblogs.com/starof/p/6370435.html
Copyright © 2011-2022 走看看