JavaScript 中的引用類型Date 和RegExp的詳細介紹
引用類型 & 引用值的理解
引用值(或者對象)是某個特定引用類型的實例。 在ECMAScript中,引用類型是把數據和功能組織到一起的結構,經常被人錯誤的稱作“類”。雖然從技術上講JavaScript 是一門面向對象語言,但ECMAScrtipt 缺少傳統的面相對象語言所具備的某些基本結構,包括類和接口。引用類型有時候也被稱為對象定義,因為它們描述瞭自己的對象應有的屬性和方法。
對象被認為是某個特定引用類型的實例。新對象通過使用new 操作符後跟一個構造函數來創建。構造函數就是用來創建新對象的函數。
let now = new Date();
這行代碼代碼創建瞭引用對象Date 的一個新實例,並將它保存在變量now 中。Date()在這裡就是構造函數,它負責創建一個隻有默認屬性和方法的簡單對象。ECMAScript 提供瞭很多像Date這樣的原生引用類型,幫助開發者實現常見的任務。函數也是一種引用類型。
Date 引用類型
ECMAScript 的Date 類型參考瞭Java 早期版本中的java.until.Date.為此,Date類型將日期保存為自協調世界時(UTC)時間1970年1月1日午夜(零時)至今所經過的毫秒數。使用這種存儲方式,Date類型可以精確的標識1970年1月1日之前及之後285616年的日期。
要創建日期對象,就是用new 操作符來調用Date構造函數:
let now = new Date(); console.log(now);// Mon Jul 18 2022 15:36:02 GMT+0800 (中國標準時間)
在不給Date 構造函數傳遞參數的情況下,創建的對象,保存的是當前的日期和時間。要基於其他日期和時間創建日期對象,必須穿入其毫秒標識。ECMAScript 為此提供瞭兩個輔助方法:Date.parse()和Date.UTC();
Date.parse()方法
Date.parse()方法接收一個表示日期和的字符串函數,嘗試將這個字符串轉換為表示該日期的毫秒數。 ECMA-262 第5版 定義瞭Date.parse()應該支持的日期格式。所有實現必須支持一下列日期格式:
- “月/日/年”,如“5/23/2022”
- “月名 日,年”,如“May 23,2022”;
- “周幾,月名 日 年 時:分:秒”,如”Tue May 23 2019 00:00:00 GMT-0700“。
如果傳給Date.parse()的字符串並不表示日期,則該方法返回NaN。如果直接把表示日期的字符串傳給Date的構造函數,那麼Date 會在後臺調用Date.parse()。換句話說,如下兩行代碼代表的意思一致。
let someDate = new Date(Date.parse("May 23,2022")); let someDateTwo = new Date("May 23,2022");
Date.UTC()方法
Date.UTC()方法也返回日期的毫秒標識,但使用的是跟Date.parse()不同的信息來生成這個值。傳給Date.UTC()的參數時年,零起點月數(1月是0,2月是1,依次類推),日(1-31),時(0-23),分,秒和毫秒。這些參數中,隻有(年和月)是必須的。如果不提供日,那麼默認為1日。其他的默認值都是0.
let y2k = new Date(Date.UTC(2000,0)); //GMT 時間2000年1月1日零點。 let allLives = new Date(Date.UTC(2005,3,5,17,55,55));// 2005年5月5日下午5點55分55秒
與Date.parse()一樣,Date.UTC也會被Date的構造函數隱式調用,但有一個區別,這種情況下創建的時本地日期,不是GMT日期。 也就是說,隱式調用情況下下,我們傳遞給Date.UTC()方法的返回的毫秒數是本地時間距離1970年1月1日的毫秒數,我們傳遞的這個日期,在JavaScript看來是UTC時間,它默認已經加上瞭時區插值的毫秒數。但是顯示的調用UTC()方法時,傳遞的日期就是GMT時間。GMT 時間與UTC 時間的關系為:GMT = UTC + 0.
let utc = new Date(2022, 6, 18, 17, 15);// console.log(utc.toString());//Mon Jul 18 2022 17:15:00 GMT+0800 (中國標準時間) console.log(new Date(Date.UTC(2022, 6, 18, 17, 15)));//Tue Jul 19 2022 01:15:00 GMT+0800 (中國標準時間)
Date.parse()方法 與Date.UTC()方法 的使用註意 首先parse方法和UTC 方法都可以隱式調用。所以我們可以這麼理解,有兩種方式可以創建日期。給Date構造函數傳入的是一個日期字符串時,會默認調用parse方法,傳入以整數的形式表示的日期會調用UTC方法。但是默認情況下我們傳遞的日期是加上瞭時區的毫秒數的,這個一定要清楚。 如果要使用UTC方法的傳遞GMT時間,一定要顯示的調用UTC()方法。
當要明確的求取某個時區的某個時間的毫秒時,需要使用parse()方法。
繼承的方法
Date 繼承自Object 方法,因此也會有toLocaleString,toString()和valueOf方法。
Date 類型重寫瞭這三個方法的實現:
- Date類型的toLocaleString()方法返回與瀏覽器運行的本地環境一致的時間和日期。這通常意味著格式中包含針對時間的AM(上午)或PM(下午),但不包含時區信息。
- toString()返回帶時區信息的日期和時間,時間也是以24小時制表示的。
- Date類型的valueOf方法根本就不返回字符串,這個方法被重寫後返回的是日期的毫秒表示。
下面是toLocaleString,toString()和valueOf的測試打印數據,可供參考。
Date(2022, 6, 14, 10, 50)
toString: Thu Jul 14 2022 10:50:00 GMT+0800 (中國標準時間)
toLocaleString: 2022/7/14 10:50:00
valueOf: 1657767000000****************************
Date.UTC(2022, 6, 14, 10, 50)
toString: Thu Jul 14 2022 18:50:00 GMT+0800 (中國標準時間)
toLocaleString: 2022/7/14 18:50:00
valueOf: 1657795800000****************************
Date.parse("Thur 07 14 2022 10:50:00 GMT+0800")
toString: Thu Jul 14 2022 10:50:00 GMT+0800 (中國標準時間)
toLocaleString: 2022/7/14 10:50:00
valueOf: 1657767000000
****************************
Date("Thur 07 14 2022 10:50:00 GMT+0800")
toString: Thu Jul 14 2022 10:50:00 GMT+0800 (中國標準時間)
toLocaleString: 2022/7/14 10:50:00
valueOf: 1657767000000
****************************
Date.now()
toString: 1657767000086
toLocaleString: 1,657,767,000,086
valueOf: 1657767000086
RegExp
ECMAScript 通過RegExp 類型支持正則表達式。正則表達式使用類似Perl 的簡介語法來創建。
let expersiion = /pattern/flags
這個正則表達式的pattern(模式)可以時任何簡單或復雜的正則表達式,包括字符類,限定符,分組,向前查找和反向引用。每個正則表達式可以帶零個或多個flags(標記),用於控制正則表達式的行為。
下面給出瞭匹配模式的標記:
- g:全局模式,表示查找字符串的全部內容,而不是找到第一個匹配的內容就結束。
- i:不區分大小寫,表示在查找匹配時忽略pattern和字符串的大小寫。
- m:多行模式,表示查找到一行末尾時會繼續查找
- y:粘貼模式,表示隻查找從lastIndex開始及之後的字符串。
- u:Unicode模式,啟用Unicode匹配。
- s:doAll模式,表示元字符,匹配任何字符(包括\n或\r).
使用不同模式和標記可以創建出各種正則表達式,比如:
//匹配字符串中的所有“at” let pattern = /at/g; //匹配第一個“bat”或“cat”,忽略大小寫 let pattern2 = /[bc]at/i; //匹配所有以“at”結尾的三字符組合,忽略大小寫。 let pattern3 = /.at/gi
與其他語言的正則表達式類似,所有元字符在模式中也必須轉義,包括: ( [ \ ^ $ |)] ? * + .
元字符在正則表達式中都有一種或多種特殊功能,所有要匹配上面這些字符本身,就必須使用反斜杠來轉義。
//匹配第一個“bat”或“cat”,忽略大小寫 let pattern2 = /[bc]at/i; //匹配第一個“[bc]at”,忽略大小寫 let pattern2 = /\[bc\]at/i; //匹配所有以“at”結尾的三字符組合,忽略大小寫。 let pattern3 = /.at/gi //匹配所有".at",忽略大小寫。 let pattern3 = /\.at/gi
前面例子中的正則表達式都是使用字面量形式定義的。正則表達式也可以使用RegExp 構造函數來創建,它接收兩個參數:模式字符串和(可選的)標記字符串。任何使用字面量定義的正則表達式也可以通過構造函數來創建:
//匹配第一個“bat”或“cat”,忽略大小寫 let pattern1 = /[bc]at/i; //跟pattern1一樣,隻不過是用構造函數創建的。 let pattern2 = new RegExp("[bc]at","i");
這裡的pattern1 和pattern2 是等效的正則表達式。註意,RegExp構造函數的兩個參數都是好字符串。因為RegExp的模式參數是字符串,所以某些情況下需要二次轉義。所有元字符都必須二次轉義,包括轉義字符,如\n(\轉義後的字符串是\,在正則表達式中則要寫成\\).
字面量模式 | 對應的字符串 |
---|---|
/[bc]at/ | "\[bc]\]at" |
/.at/ | "\at." |
/name/age/ | "name\/age" |
/\d/\d{1,2} | "\d.\d{1,2}" |
/\w\hello\123 | "\w\\hello\\123" |
RegExp 實例方法
exec()
RegExp的主要方法是exec(),主要用於配合捕獲組使用。這個方法隻接受一個參數,即要應用模式的字符串。如果找到瞭匹配項,則返回包含第一個匹配信息的數組;如果沒有找到匹配項,則返回null。返回的數組雖然是Array的實例,。但包含兩個額外的屬性:index和input。index是字符串中匹配模式的起始位置,input 是要查找的字符串。這個數據的第一個元素是匹配整個模式的字符串,其他元素食欲表達式中的捕獲組匹配的字符串。如果模式中沒有捕獲組,則數組隻包含一個元素。
let text = "mom and dad and baby"; let pattern = /mom( and dad( and baby)?)?/gi let matches = pattern.exec(text); console.log(matches.index); //0 console.log(matches.input); //"mom and dad and baby" console.log(matches[0]);// "mom and dad and baby" console.log(matches[1]);// " and dad and baby" console.log(matches[2]);// " and baby"
在這個例子中,模式包含兩個捕獲組:最內部的匹配項“ and baby”,以及外部的匹配項“ and dad” 或“ and dad and baby”。調用exec()後找到瞭一個匹配項。因為整個字符串匹配模式,所以matches數組的index 屬性就是0。數組的第一個元素是匹配的整個字符串,第二個元素是匹配第一個捕獲組的字符串,第三個元素是匹配第二個捕獲組的字符串。 如果模式設置瞭全局標記,則每次調用exec()方法會返回一個匹配的信息。如果沒有設置全局標記,則無論對同一個字符串調用多少次exec(),也隻會返回第一個匹配的信息。
let text = "cat, bat, sat, fat"; let pattern = /.at/; let matches = pattern.exec(text); console.log(matches.index);//0 console.log(matches[0]);//cat console.log(pattern.lastIndex);//0 matches = pattern.exec(text); console.log(matches.index);//0 console.log(matches[0]);//cat console.log(pattern.lastIndex);//0
上面的例子沒有設置全局標記,因此調用exec()隻返回第一個匹配項("cat").lastIndex 在非全局模式下始終不變。
如果在這個模式上設置瞭g標記,則每次調用exec()都會在字符串向前搜索下一個匹配項。
let text = "cat, bat, sat, fat"; let pattern = /.at/g; let matches = pattern.exec(text); console.log(matches.index);//0 console.log(matches[0]);//cat console.log(pattern.lastIndex);//3 matches = pattern.exec(text); console.log(matches.index);//5 console.log(matches[0]);//bat console.log(pattern.lastIndex);//8 matches = pattern.exec(text); console.log(matches.index);//10 console.log(matches[0]);//sat console.log(pattern.lastIndex);//13
如果設置瞭粘附標記y,則每次調用exec()就隻會在lastIndex的位置上尋找匹配項。
粘附標記會覆蓋全局標記:
let text = "cat, bat, sat, fat"; let pattern = /.at/y; let matches = pattern.exec(text); console.log(matches.index);//0 console.log(matches[0]);//cat console.log(pattern.lastIndex);//3 //以索引3對應的字符開頭找不到匹配項,因此exec() 返回null // matches = pattern.exec(text); console.log(matches);//null console.log(pattern.lastIndex);//0 //向前設置lastIndex 可以讓粘附的模式通過exec()找到下一個匹配項。 pattern.lastIndex = 5; matches = pattern.exec(text); console.log(matches.index);//5 console.log(matches[0]);//bat console.log(pattern.lastIndex);//8
test()
正則表達式的另一個方法是test(),接收一個字符串參數。如果輸入的文本與模式匹配,則參數返回true,否則返回false。這個方法適用於隻想測試模式是否匹配,而不需要世界匹配內容的情況。
let text = "000-00-0000"; let pattern = /\d{3}-\d{2}-\d{4}/; if(pattern.test(test)){ console.log("The pattern was matched."); }
繼承的方法
無論正則表達式怎麼創建的,繼承的方法toLocalString()toString()都返回正則表達式的字面量表示。
let pattern = new RegExp("\\[bc]\\at]at","gi"); console.log(pattern.toString()); ///\[bc\]at/gi console.log(pattern.toLocaleString()); // /\[bc\]at/gi console.log(pattern.valueOf());///\[bc]\at]at/gi
到此這篇關於JavaScript 中的引用類型Date 和RegExp的詳細介紹的文章就介紹到這瞭,更多相關JS引用類型Date和 RegExp內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- JavaScript高級程序設計之基本引用類型
- 正則表達式regular expression詳述(二)284278示例
- 正則表達式regular expression詳述(一)284278問題及解決
- JavaScript中時間格式化新思路toLocaleString()
- JavaScript 引用類型之原始值包裝類型String