class IsType { // 构造函数 constructor(type) { type = type || ''; this.type = type.toLowerCase(); } // 类型处理 checkType(obj) { let val = Object.prototype.toString.call(obj); val = val.slice(1, val.length - 1); val = val.split(' ')[1]; val = val.toLowerCase(); return val === this.type; } // 判断是否存在‘{}’或‘[]’ matchString(obj) { // 把obj转为JSON字符串 let toStr = JSON.stringify(obj); // 通过indexOf查找字符串是否存在‘{}’或‘[]’ return toStr.indexOf('{}') !== -1 || toStr.indexOf('[]') !== -1; } // 最终通过判断返回布尔值 Boolean rationality(obj) { if (this.checkType(obj) && !this.matchString(obj) && Object.keys(obj).length > 0) { return true; } else if (this.checkType(obj) && !this.matchString(obj) && obj.length > 0) { return true; } else { return false; } } } let a = new IsType('Array'), o = new IsType('object'); console.log(a.rationality()); // false console.log(a.rationality([7])); // true console.log(a.rationality([7, []])); // false console.log(o.rationality({ id: 2, list: [6], l: [9] })); // true console.log(o.rationality({ id: 2, list: [6], l: [] })); // false
步骤一:使用class定义一个名为IsType的类,在JavaScript中类自带constructor构造函数,函数主要功能是接收new时传递的值,并通过this存储值。在此案例中传入函数的值分别是Array和object两个字符串,并通过toLowerCase方法把值转为小写,最后把值存储起来,此操作与JavaScript闭包机制类似。
步骤二:checkType函数主要作用是获取传入值的类型。函数里面的第一行代码使用了判断类型最原始最可靠的方法,此操作会得到一个这样的值[object Array],其中Array是可变值,对应JavaScript的所有类型值。第二行代码通过slice方法截取对应值,操作得到的结果是object Array。第三行代码通过split方法把字符串按空格分割成数组,并且获取数组第二项的值。第三行代码通过toLowerCase方法把得到的字符串全部转换成小写。最终在return的时候把得到的字符串与构造函数中存储的字符串进行对比返回对应的布尔值Boolean。
步骤三:matchString函数做的事情是判断传进来的值里面是否存在{}或[]这两个字符串中的任何一个,如果有则返回true,否则返回false。函数里的第一行代码使用JSON的stringify方法把值转为JSON字符串。第二行代码通过indexOf查找字符串是否存在{}或[],并返回对应的布尔值Boolean。
步骤四:rationality函数做了最终的处理,对于使用者来说,只需要调用此函数即可,因为以上所有代码将被封装在某个.js文件里面,并且会向外面暴露rationality函数供使用者调用。函数里面的第一行代码是if判断,这是对Object对象类型的数据进行判断,在判断中先调用checkType函数,接着调用matchString函数,最后是通过Object的keys方法判断对象长度是否大于0,只有这三个条件都满足的时候才会返回true;第三行又是一个if判断,此判断是对Array数组类型进行判断,依然需要调用先前的两个函数,不同之处在于通过数组的length方法直接判断数组长度是否大于0,跟判断对象一样都使用且&&操作符,且操作符表示当条件都满足才返回true。当两个if都不满足的时候,就说明传入的值既不是Object类型值,也不是Array类型值,所以返回false,此处还可以做拓展,比如判断是String、Number等其他类型数据。值得注意的是在调用matchString函数时取反,如果不是很理解,可以多看几次步骤三就明白了为什么取反了。
最后就是怎么调用的问题了,首先使用new关键字调用类,并且在调用的时候传入对应的数据类型作为匹配实参,用new调用后会得到一个类的实例,可以定义一个变量把实例存储起来备用。第二步就是通过调用实例里面的rationality方法实现最终的判断,当然在调用rationality方法时需要传入相应的值,也可以不传。