在最近一個專案中,表單驗證需要對時間的起止範圍進行判斷:結束時間需大於或等於開始時間。即:結束年須大於起始年;若相等,則比較起始月與結束月;若起止月也相等,則比較日期。那麼,對於每一次驗證,可以用下面這個函數來比較。
function compare(begin,end,error){
var begin = parseInt(begin,10);
var end = parseInt(end,10);
var diff = end - begin;
if(diff < 0){
alert(error);
}else{
return true;
}
}
這樣,在驗證的時候,只要結果回傳真就表示通過。如:
var year = compare(2001,2003,'年');
var month = compare(1,2,'月');
var day = compare(12,13,'天');
alert(year && month && day); //結果為真------"true"
將上面的起止月份和起止日期修改一下。如:
var year = compare(2001,2003,'年');
var month = compare(3,2,'月');
var day = compare(24,13,'天');
alert(year && month && day); /結果為假------"false"
執行結果,依次顯示”月”,“天”,”false”;實際上,當起止月份不正確的時候,我們沒必要對日期進行驗證;月份驗證的前提條件是年驗證通過;天驗證的前提是月份驗證通過。仔細分析之後,我決定將上面函數的三個參數用單體模式儲存起來,也就是:
{
begin:2001,
end:2003,
error:"結束年限須大於起始年限"
}
但是,我又不想定義函數的參數,函數能否根據傳遞的參數自動進行驗證了?答案是肯定的。在函數的開始,先判斷參數的個數,如果大於1,則含有遞歸處理。如何做到遞迴處理呢?我在函數內部作瞭如下處理:
var len = arguments.length;
if(len > 1){
var args = Array.prototype.slice.call(arguments);
args.shift(); //將第一個參數移除,餘下的用作遞歸處理的參數
}
對於arguments,我們不能直接呼叫Array.shift()方法。雖然arguments有length屬性,但畢竟不是數組,所以用Array.slice()方法將其轉換成數組。關於arguments,在網路上可以了解到更多的信息,這裡不在贅述。為什麼只有在len大於1時才進行處理呢?因為參數為1時,就不需要進行下一步驗證了。遞歸處理在什麼時候進行呢?仔細想想,只有在初始值與結束值相等時才需要,明白了這些,我們就很容易建構我們的驗證函數了。
var diff = parseInt(arguments[0].end,10) - parseInt(arguments[0].begin,10);
if(diff <0 ){
alert(arguments[0].error);
return false;
}else if(diff == 0){
return len > 1 ? arguments.callee.apply(this,args) : true;
}else{
return true;
}
上面的程式碼中,arguments.callee是函數自身,關於apply的用法可以在web找到相關資料。
到此驗證函數已經完成,但需要注意的是:
到此已經結束,看看範例。有時候,我們不想以alert的方式顯示錯誤訊息,我們可以自訂處理函數將其作為最後一個參數傳入其中。那麼在函數的開始,取得處理函數,如:
var func = arguments[len - 1];
if(typeof func == 'function'){
func(arguments[0]);
}
所以,最終的處理函數是這樣的:
function compare(){
var len = arguments.length;
var func = arguments[len - 1];
if(len > 1){
var args = Array.prototype.slice.call(arguments);
args.shift(); //將第一個參數移除,餘下的用作遞歸處理的參數
}
var diff = parseInt(arguments[0].end,10) - parseInt(arguments[0].begin,10);
if(diff <0 ){
(typeof func == 'function') ? func(arguments[0].error) : alert(arguments[0].error);
return false;
}else if(diff == 0){
return len > 1 ? arguments.callee.apply(this,args) : true;
}else{
return true;
}
}
function compare(){
var len = arguments.length;
if(len > 1){
var args = Array.prototype.slice.call(arguments);
args.shift(); //將第一個參數移除,餘下的用作遞歸處理的參數
}
var diff = parseInt(arguments[0].end,10) - parseInt(arguments[0].begin,10);
if(diff <0 ){
alert(arguments[0].error);
return false;
}else if(diff == 0){
return len > 1 ? arguments.callee.apply(this,args) : true;
}else{
return true;
}
}