Javascript類型判斷相關(guān)例題及解析
題目:
請?jiān)趇ndex.html文件中,編寫arraysSimilar函數(shù),實(shí)現(xiàn)判斷傳入的兩個(gè)數(shù)組是否相似。具體需求:
1. 數(shù)組中的成員類型相同,順序可以不同。例如[1, true] 與 [false, 2]是相似的。
2. 數(shù)組的長度一致。
3. 類型的判斷范圍,需要區(qū)分:String, Boolean, Number, undefined, null, 函數(shù),日期, window.
當(dāng)以上全部滿足,則返回"判定結(jié)果:通過",否則返回"判定結(jié)果:不通過"。
一、測試用例
var result=function(){
//以下為多組測試數(shù)據(jù)
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循環(huán), 通過arraysSimilar函數(shù)驗(yàn)證以上數(shù)據(jù)是否相似,如相似顯示“通過”,否則"不通過",所以大家要完成arraysSimilar函數(shù),具體要求,詳見任務(wù)要求。
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)+" 的判斷結(jié)果不是"+cases[i].expect);
return false;
}
}
return true;
}();
document.write("判定結(jié)果:"+(result?"通過":"不通過"));
這個(gè)文件為testData.js。主要任務(wù)是完成arraysSimilar函數(shù)。
二、arraySimilar函數(shù)
1、我的寫法
1、判斷2個(gè)參數(shù)是否都是數(shù)組,不是就返回false;
2、判斷2個(gè)數(shù)組長度是否一致,不是直接返回fasle;
3、新建2個(gè)臨時(shí)數(shù)組temp1,temp2并初始化為0,用來存放arr1和arr2中各種類型的個(gè)數(shù)。
var temp1 = [0, 0, 0, 0, 0, 0, 0, 0];
var temp2 = [0, 0, 0, 0, 0, 0, 0, 0];
4、遍歷2個(gè)arr1和arr2,每遍歷一個(gè)元素,將對應(yīng)類型加1。
5、完成arr1和arr2的遍歷后,通過temp1.toString()和temp2.toString()是否相等得出2個(gè)數(shù)組是否相似。
<!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 + "個(gè)值為" + 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 + "個(gè)值為" + 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;
}
}
//返回參數(shù)的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以下) //看了答案發(fā)現(xiàn)直接=== 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 //看了答案發(fā)現(xiàn)直接=== window 判斷就好了
if (arg instanceof Window) {
console.log("window");
return "Window";
}
}
</script>
<script src="testData.js"></script>
</body>
</html>
雖然代碼略粗糙,但是功能完成了。網(wǎng)上看了其他人的答案確實(shí)不同的人做法不一樣,有些值得借鑒的地方。
2、其他答案
建一個(gè)類型對象數(shù)組obj,初始化為零,arr1遍歷時(shí)每個(gè)元素對應(yīng)的類型加一,arr2遍歷時(shí)每個(gè)元素對應(yīng)的類型減一,最終判斷obj里所有鍵的值都為0即相似數(shù)組。
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;
}
還有一個(gè)答案,差不多算標(biāo)準(zhǔn)答案,當(dāng)然這種題也沒有標(biāo)準(zhǔn)答案。和上個(gè)答案的差別是,用map(在js中也就是對象)存放數(shù)據(jù)類型和次數(shù),這個(gè)map初始化為{},在后面動態(tài)生成的。
/**
* String, Boolean, Number, undefined, null, 函數(shù),日期, window
*/
function arraysSimilar(arr1, arr2) {
// 判斷參數(shù),確保arr1, arr2是數(shù)組,若不是直接返回false
if (!(arr1 instanceof Array)
|| !(arr2 instanceof Array)) {
return false;
}
// 判斷長度
if (arr1.length !== arr2.length) return false;
var i = 0,
n = arr1.length,
countMap1 = {}, // 用來計(jì)算數(shù)組元素?cái)?shù)據(jù)類型個(gè)數(shù)的map,key是TYPES中的類型字符串,value是數(shù)字表示出現(xiàn)次數(shù)。
countMap2 = {},
t1, t2,
TYPES = ['string', 'boolean', 'number', 'undefined', 'null',
'function', 'date', 'window'];
// 因?yàn)槭菬o序的,用一個(gè)對象來存儲處理過程。key為類型, value為該類型出現(xiàn)的次數(shù)。
// 最后校驗(yàn):若每一種數(shù)據(jù)類型出現(xiàn)的次數(shù)都相同(或都不存在),則證明同構(gòu)。
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;
}
}
// 因?yàn)閠ypeof只能判斷原始類型,且無法判斷null(返回"object"),所以自己寫typeof方法擴(kuò)展。
function typeOf(ele) {
var r;
if (ele === null) r = 'null'; // 判斷null
else if (ele instanceof Array) r = 'array'; // 判斷數(shù)組對象
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;
}
還有一個(gè)比較簡潔也好理解的解法
<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>
還有一個(gè)精妙的解法,我對這種不感興趣,沒仔細(xì)看。
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());
}
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
解決canvas畫布使用fillRect()時(shí)高度出現(xiàn)雙倍效果的問題
下面小編就為大家?guī)硪黄鉀Qcanvas畫布使用fillRect()時(shí)高度出現(xiàn)雙倍效果的問題。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-08-08
ES6新特性三: Generator(生成器)函數(shù)詳解
這篇文章主要介紹了ES6新特性之Generator(生成器)函數(shù),簡單分析了Generator(生成器)函數(shù)的功能、定義、調(diào)用方法并結(jié)合實(shí)例形式給出了相關(guān)使用技巧,需要的朋友可以參考下2017-04-04
微信小程序scroll-view橫向滑動嵌套for循環(huán)的示例代碼
這篇文章主要介紹了微信小程序scroll-view橫向滑動嵌套for循環(huán)的示例代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-09-09
javascript實(shí)現(xiàn)json頁面分頁實(shí)例代碼
這篇文章主要介紹了javascript實(shí)現(xiàn)json頁面分頁實(shí)例代碼,需要的朋友可以參考下2014-02-02
基于JS簡單實(shí)現(xiàn)手持彈幕功能+文字抖動特效代碼
這篇文章主要介紹了基于JS簡單實(shí)現(xiàn)手持彈幕功能+文字抖動特效代碼,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-03-03

