任务
请在 index.html 文件中,编写 arraysSimilar 函数,实现判断传入的两个数组是否相似。具体需求:
- 数组中的成员类型相同,顺序可以不同。例如 [1, true] 与 [false, 2] 是相似的。
- 数组的长度一致。
- 类型的判断范围,需要区分: String , Boolean, Number, undefined, null, 函数, 日期, window. 当以上全部满足,则返回"判定结果:通过",否则返回"判定结果:不通过"。
这是一个奇怪的需求,主要是要求“相似”的判断。
- 第一直觉是直接对数组排序,然后比较类型。但由于 JS 比较大小的特性,这是不对的。
- 那么需要变换一下,我这里是取每个元素的类型名简写,这样可以近似 \(O(NlogN)\) 排字典序,再将其作为整个数组的 typo ,就可以近似 \(O(N)\) 比较数组是否相似。
- 第二个要注意的点是对无效参数的判断,一开始是用
== null
来判断null
和undefined
的,但是要求参数类型为数组,所以用instanceof
判断。 - 获取类型的替代方案是用
Object.prototype.toString()
,可以准确地拿到原型链上对象的类名,但是函数可能会被重写,所以不优先使用。 - 但其实使用
instanceof
是有问题的,考虑不同页面的构造函数可以不同——因此判断数组可以用Array.isArray()
代替,
/* * param1 Array * param2 Array * return true or false */ function arraysSimilar(arr1, arr2) { // 获取单个元素的类型名简写,已经满足需求 // 替代方案:考虑用 Object.prototype.toString ,但会被 hack function getTypeNameS(item) { if (item === null) return 'nl'; else if (item instanceof Date) return 'd'; else if (item instanceof Window) return 'w'; else return (typeof item)[0]; } // 获取整个数组排序后的 typo function getArrayTypo(arr) { return arr.map(function (item) { return getTypeNameS(item); }).sort().join(''); } // 可以判断 == null ,但由于要求类型为数组,那就用 instanceof if (!(arr1 instanceof Array) || !(arr2 instanceof Array)) return false; // 长度不等的情况,也可以合并到 typo 比较中 if (arr1.length != arr2.length) return false; // 对于 typo 使用内置的字符串比较 return getArrayTypo(arr1) == getArrayTypo(arr2); }
下面是另一种实现:
function arraysSimilar(arr1, arr2) { // 用 Object.prototype.toString ,但会被 hack function getTypeName(item) { return item === null ? 'Null' : Object.prototype.toString.call(item).slice(8, -1); } // 获取整个数组排序后的 typo function getArrayTypo(arr) { return arr.map(function (item) { return getTypeName(item); }).sort().join(''); } // 使用 ECMAScript 5.1 的 isArray() 函数 if (!Array.isArray(arr1) || !Array.isArray(arr2)) return false; // 长度不等的情况 if (arr1.length != arr2.length) return false; // 对于 typo 使用内置的字符串比较 return getArrayTypo(arr1) == getArrayTypo(arr2); }
本文发布,欢迎引用、转载或演绎,但是必须保留本文的署名以及本文链接,且未经许可不能用于商业目的。如有疑问或授权协商请。