寫這個(gè)鼎兽,其實(shí)是有一次送測(cè)時(shí)提的bug,當(dāng)時(shí)對(duì)這個(gè)問題不解铣除,后來花了點(diǎn)時(shí)間理解了之后谚咬,才知道大概是怎么回事。
先看下當(dāng)初的代碼吧(大概的):
var consumerType = $("#consumerType").val();
if(0 == consumerType){
……
}
獲取id為consumerType的value通孽,判斷其是否為0序宦。問題就出在這個(gè)0判斷上。id為consumerType的那個(gè),是一個(gè)可輸入互捌,也可從后端傳過來潘明。當(dāng)時(shí)這個(gè)值為空,但是這個(gè)相等判斷就為true秕噪,然后就緊接著跟著一段操作钳降。
為什么這個(gè)地方會(huì)錯(cuò)呢,我們逐步分析腌巾。
1遂填、JavaScript中的類型
JavaScript中的類型是松散類型,也是弱類型澈蝙。就是聲明一個(gè)變量后吓坚,只是分配一個(gè)內(nèi)存出來,可以對(duì)這個(gè)變量賦整數(shù)(向這個(gè)內(nèi)存寫入整數(shù)或者其他類型)灯荧,也可以賦時(shí)間礁击,也可以賦數(shù)組。同時(shí)不同的類型之間有一定的轉(zhuǎn)換關(guān)系逗载。
松散類型:
var s ;
s = 1;
s = 'adsa';
s = {};
弱類型:
var s = 1;
var v = 'a';
var sv = 1 + 'a';
JavaScript有6種數(shù)據(jù)類型哆窿,分別是number、string厉斟、object挚躯、Boolean、function擦秽、undefined码荔。
"undefined" 如果值未定義 Undefined
"boolean" 如果這個(gè)值是布爾值 Boolean
"string" 如果這個(gè)值是字符串 String
“number” 如果這個(gè)值是數(shù)值類型 Number
“object” 如果這個(gè)值是對(duì)象或null Object
“function” 如果這個(gè)值是函數(shù) Function
想知道類型,用typeof
2感挥、typeof
知道了幾種類型目胡,那么如果我想知道這個(gè)對(duì)象的類型,那么使用typeof即可知道其類型链快。
但是還有一種,非基礎(chǔ)類型:
var a = [];
數(shù)組類型眉尸,怎么知道呢域蜗?也有,instanceof噪猾。
var a = [];
console.log(a instanceof Array) //返回true
instanceof與Java中的instanceof作用類似吧霉祸。
3、相等判斷
3.1袱蜡、等號(hào)的類型
在JavaScript中丝蹭,等號(hào)的類型有兩種:相等、全等
var a = 1;
var b = '1';
console.log(a == b);
console.log(a != b);
console.log(a === b);
console.log(a !== b);
相等用于基本類型判斷坪蚁,全等用于對(duì)象判斷奔穿。
3.2 相等隱式類型轉(zhuǎn)換
對(duì)于相等為何上面 a == b還可以成立呢镜沽,原因是有以下隱式類型轉(zhuǎn)換:
- 如果一個(gè)運(yùn)算數(shù)是 Boolean 值,在檢查相等性之前贱田,把它轉(zhuǎn)換成數(shù)字值缅茉。false 轉(zhuǎn)換成 0,true 為 1男摧。
- 如果一個(gè)運(yùn)算數(shù)是字符串蔬墩,另一個(gè)是數(shù)字,在檢查相等性之前耗拓,要嘗試把字符串轉(zhuǎn)換成數(shù)字拇颅。
- 如果一個(gè)運(yùn)算數(shù)是對(duì)象,另一個(gè)是字符串乔询,在檢查相等性之前樟插,要嘗試把對(duì)象轉(zhuǎn)換成字符串。
- 如果一個(gè)運(yùn)算數(shù)是對(duì)象哥谷,另一個(gè)是數(shù)字岸夯,在檢查相等性之前,要嘗試把對(duì)象轉(zhuǎn)換成數(shù)字们妥。
在轉(zhuǎn)換的同時(shí)猜扮,還有以下原則:
- 值 null 和 undefined 相等。
- 相等性檢查時(shí)监婶, null 和 undefined 不會(huì)轉(zhuǎn)換成其他值旅赢。
- 若某個(gè)運(yùn)算數(shù)是 NaN,等號(hào)將返回 false惑惶,非等號(hào)將返回 true煮盼。
- 如果兩個(gè)運(yùn)算數(shù)都是對(duì)象,那么比較的是它們的引用值带污。如果兩個(gè)運(yùn)算數(shù)指向同一對(duì)象僵控,那么等號(hào)返回 true,否則兩個(gè)運(yùn)算數(shù)不等
在這可以看出鱼冀,NaN == NaN 為false(這個(gè)邏輯也是醉了)报破。
那么對(duì)下面的代碼,可以想想結(jié)果:
var a = '';
var b = 0;
var c = null;
var d;
console.log(a == b);
console.log(a == c);
console.log(a == d);
console.log(b == c);
console.log(b == d);
console.log(c == d);
console.log(a == NaN);
以及下面的代碼:
var a = 11, b = '22';
var c = a + b;
console.log(c);
var d = 11, e = '5';
var f = d - e;
console.log(typeof f);
3.3 對(duì)象判等
js的對(duì)象判等采用的是值&&地址一致千绪,才判等充易,因此對(duì)象判等尤其需要注意。
var obj1 = {
name: "zzz",
sex : "1"
}
var obj2 = {
name: "ccc",
sex : "2"
}
var obj3 = obj1;
//true
console.log(obj1 == obj3);
//true
console.log(obj1 === obj3);
//false
console.log(obj2 == obj3);
//false
console.log(obj2 === obj3);
那么如何在JavaScript內(nèi)判斷兩個(gè)對(duì)象相等呢荸型?直接對(duì)對(duì)象進(jìn)行判斷已經(jīng)證明是不可行的盹靴,那么就只有對(duì)其中的屬性進(jìn)行逐個(gè)遍歷進(jìn)行判斷。
不過在實(shí)際開發(fā)的過程中,極少在前端進(jìn)行對(duì)象的相等判斷稿静。而且知道了java對(duì)象的相等判斷原則后梭冠,就更不會(huì)在前端做相等判斷了(場(chǎng)景不多,并且個(gè)人感覺在前端做這種邏輯判斷不太靠譜)自赔。
4 全等判斷
全等號(hào)是使用三個(gè)等號(hào)判斷妈嘹,只有在運(yùn)算數(shù)就相等的情況下,才返回 true绍妨。
var sNum = "66";
var iNum = 66;
console.log(sNum == iNum);
console.log(sNum === iNum);
5润脸、日期相等判斷
從另一個(gè)角度來說,日期時(shí)間類型也是一個(gè)對(duì)象他去。那么看完上面的介紹毙驯,你肯定就知道了,作為日期對(duì)象灾测,肯定不能簡單的用 == 進(jìn)行判等爆价。有兩種思路:
1)將該時(shí)間字符串轉(zhuǎn)換成時(shí)間對(duì)象。
var startTime = $("#startTime").val();
var endTime = $("#endTime").val();
var starttime = new Date(startTime);
var endtime = new Date(endTime);
var deviation = parseInt((endtime.getTime() - starttime.getTime()) / 1000);
if(0 != deviation){
……
}
2)逐個(gè)比較其中的年月日媳搪。
function isEqualDay (date1铭段,date2) {
return date1.getFullYear() === date2.getFullYear()
&& date1.getMonth() === date2.getMonth()
&& date1.getDate() === date2.getDate() ;
}
當(dāng)然了,如果有時(shí)分秒秦爆,也是一樣的邏輯序愚。
6、實(shí)例
6.1 數(shù)組下標(biāo)處理
背景描述:開發(fā)一個(gè)可自由新增行等限、刪除行的代碼
在新增行的時(shí)候爸吮,找到一個(gè)未使用過的行下標(biāo):
var table = document.querySelector('#thresholdTable tbody');
var rowCount = table.rows.length;
for(var i=0;;i++){
var down = document.getElementsByName("useThresholdList["+i+"].amountDown");
rowCount = i;
break;
}
其中rowCount為找到的行下標(biāo)。這樣看是不是沒問題望门。實(shí)際上有問題形娇,由于可能進(jìn)行了刪除操作,那么其中第i行可能不存在筹误,代碼應(yīng)改為如下:
var table = document.querySelector('#thresholdTable tbody');
var rowCount = table.rows.length;
for(var i=0;;i++){
var down = document.getElementsByName("useThresholdList["+i+"].amountDown");
if(undefined != down && '' != down && undefined != down[0]){
continue;
}
rowCount = i;
break;
}
6.2 頁面空字段判斷
在開發(fā)的時(shí)候桐早,經(jīng)常遇到一個(gè)問題,就是判斷頁面的input厨剪、select等輸入勘畔、選擇框判斷是否有值。
這里丽惶,一樣有2種開發(fā)思路
1)自定義標(biāo)簽
這個(gè)也是之前一次同事的技術(shù)開發(fā)分享時(shí)提到的。
自定義一個(gè)標(biāo)簽爬立,isNotNull,在進(jìn)行submit的時(shí)候?qū)λ袚碛羞@類標(biāo)簽的輸入框都進(jìn)行類似的校驗(yàn)钾唬。
這樣做的好處很明顯,在業(yè)務(wù)有變化的時(shí)候,只需要移除或者重新校驗(yàn)帶有該標(biāo)簽的所有輸入框即可抡秆。
2)逐個(gè)校驗(yàn)
根據(jù)id或者name奕巍,逐個(gè)獲取進(jìn)行校驗(yàn),類似于以下的代碼:
if(undefined != down
&& '' != down
&& undefined != down[0]){
……
}
7儒士、后話
寫這篇文章的時(shí)候的止,距離發(fā)生這個(gè)問題已經(jīng)過了很久了。當(dāng)時(shí)記下了這個(gè)問題着撩,時(shí)過境遷诅福,問題的出處都已經(jīng)找不到了。
這篇文章寫的比較淺拖叙,僅供大家一看氓润。