萬盛學電腦網

 萬盛學電腦網 >> 腳本專題 >> javascript >> JavaScript自定義日期格式化函數詳細解析

JavaScript自定義日期格式化函數詳細解析

 下面的一個例子就是以獨立函數寫出的JavaScript日期格式化函數,獨立的format函數。回到格式化的這一知識點上,我們考查的是怎麼實現的、運用了哪些原理

我們對 JavaScript 擴展其中一個較常的做法便是對 Date.prototype 的擴展。因為我們知道,Date 類只提供了若干獲取日期元素的方法,如 getDate(),getMinute()……卻沒有一個轉換為特定字符串的格式化方法。故所以,利用這些細微的方法,加以封裝,組合我們想要的日期字符串形式。一般來說,該格式化函數可以定義在 Date 對象的原型身上,也可以獨立一個方法寫出。定義原型方法的操作如 Date.prototype.format = function(date){……},使用時候直接 new Date().format(YYYY:MM:DD) 即可,仿佛就是 Date 對象的原生方法。但是定義原型方法卻略嫌有“入侵” JS 原型的不足。設計 API 之時必須考慮這個問題。我的建議是,用戶按照自己的判斷去做決定,只是調用的方式不同,不影響過程的邏輯即可。   下面的一個例子就是以獨立函數寫出的 JavaScript 日期格式化函數,獨立的 format 函數。回到格式化的這一知識點上,我們考查的是怎麼實現的、運用了哪些原理。傳統字符串拼接如 indexOf()+substr() 雖然能夠實現,但明顯不僅效率低下,而且代碼冗長,還是適宜引入正則表達式的方法,先寫出字符串正則然後再進行結果的命中匹配。我們先看看來自 Steven Levithan 的例子:   代碼如下: /**  * Date Format 1.2.3  * @credit Steven Levithan <stevenlevithan.com> Includes enhancements by Scott Trenda <scott.trenda.net> and Kris Kowal <cixar.com/~kris.kowal/>  * Accepts a date, a mask, or a date and a mask.  * Returns a formatted version of the given date.  * The date defaults to the current date/time.  * The mask defaults to dateFormat.masks.default.  */ dateFormat = (function(){     // 正則筆記, 1、token,(?:)表示非捕獲分組;/1 反向引用(思考:{1,2}可否和/1一樣意思?);根據這裡的意義[LloSZ]表示括號內的任意一個字符拿去匹配,很簡單,但暫時不明白/L|l|o|S|Z/在解析日期時的作用;最後的兩組“或”是匹配引號和引號內的內容(無所謂雙引號或單引號)。     var token        = /d{1,4}|m{1,4}|yy(?:yy)?|([HhMsTt])/1?|[LloSZ]|"[^"]*"|'[^']*'/g,     // 2、timezone, [PMCEA][SDP]產生兩個字符的消耗;該reg的都是非捕獲分組,可加快正則速度。         timezone     = //b(?:[PMCEA][SDP]T|(?:Pacific|Mountain|Central|Eastern|Atlantic) (?:Standard|Daylight|Prevailing) Time|(?:GMT|UTC)(?:[-+]/d{4})?)/b/g,         timezoneClip = /[^-+/dA-Z]/g,           // 不足兩位填充字符,或可指定位數         pad          = function (val, len){             val = String(val);             len = len || 2;             while (val.length < len) val = "0" + val;             return val;         };     // 為什麼返回一個function,因為前面說明的變量都變作常量,下面返回的參數才是真正到時執行的函數。這一點透過閉包的寫法來實現。如英文注釋說的,可以提速。     // Regexes and supporting functions are cached through closure     // 參數說明:date: Date 被解析的日期或新日期;mask:String 格式化日期的模板;utc:Stirng 可選的UTC。     return function (date, mask, utc) {         var i18n  = dateFormat.i18n;         var masks = dateFormat.masks;         // You can't provide utc if you skip other args (use the "UTC:" mask prefix)         // 如果只有一個參數,其該參數是不包含數字的字符串,則視作這個參數為mask。date由下一個if中的new Date產生,那麼date就是現在的日期。         if (arguments.length == 1 && Object.prototype.toString.call(date) == "[object String]" && !//d/.test(date)) {             mask = date;             date = undefined;         }           // Passing date through Date applies Date.parse, if necessary         date = date ? new Date(date) : new Date;         if (isNaN(date)) throw SyntaxError("invalid date");         // 通過判斷多種情況明確mask是什麼,不論前面是如何指定的。留意 || 的技巧。         mask = String(masks[mask] || mask || masks["default"]);         // Allow setting the utc argument via the mask         if (mask.slice(0, 4) == "UTC:") {             mask = mask.slice(4);             utc = true;         }         // 分兩種情況,用UTC格式的情況和一般的。注意通過JS的字面索引也可以返回方法的成員。         var _ = utc ? "getUTC" : "get",             d = date[_ + "Date"](),             D = date[_ + "Day"](),             m = date[_ + "Month"](),             y = date[_ + "FullYear"](),             H = date[_ + "Hours"](),             M = date[_ + "Minutes"](),             s = date[_ + "Seconds"](),             L = date[_ + "Milliseconds"](),             o = utc ? 0 : date.getTimezoneOffset(),             flags = {                 d:    d,                 dd:   pad(d),                 ddd:  i18n.dayNames[D],                 dddd: i18n.dayNames[D + 7],// 位寬:7, 見 dateFormat.dayNames。                 m:    m + 1, // 從0開始起月份                 mm:   pad(m + 1),                 mmm:  i18n.monthNames[m],                 mmmm: i18n.monthNames[m + 12], // 位寬:12,見 dateFormat.monthNames                 yy:   String(y).slice(2),// 字符串slice()的用法                 yyyy: y,                 h:    H % 12 || 12, // h表示12小時制,h除以12(因為十二進制),取余的結果為12小時制的。                 hh:   pad(H % 12 || 12),                 H:    H,                 HH:   pad(H),                 M:    M,                 MM:   pad(M),                 s:    s,                 ss:   pad(s),                 l:    pad(L, 3), // Max,999ms                 L:    pad(L > 99 ? Math.round(L / 10) : L),                 // 大小寫有影響                 t:    H < 12 ? "a"  : "p",                 tt:   H < 12 ? "am" : "pm",                 T:    H < 12 ? "A"  : &quo
copyright © 萬盛學電腦網 all rights reserved