天天看點

JavaScript(四)标準對象

在javascript中,​<code>​date​</code>​對象用來表示日期和時間。

要擷取系統目前時間,用:

注意,目前時間是浏覽器從本機作業系統擷取的時間,是以不一定準确,因為使用者可以把目前時間設定為任何值。

如果要建立一個指定日期和時間的​<code>​date​</code>​對象,可以用:

你可能觀察到了一個非常非常坑爹的地方,就是javascript的月份範圍用整數表示是0~11,​<code>​0​</code>​表示一月,​<code>​1​</code>​表示二月……,是以要表示6月,我們傳入的是​<code>​5​</code>​!這絕對是javascript的設計者當時腦抽了一下,但是現在要修複已經不可能了。

第二種建立一個指定日期和時間的方法是解析一個符合​​iso 8601​​格式的字元串:

但它傳回的不是​<code>​date​</code>​對象,而是一個時間戳。不過有時間戳就可以很容易地把它轉換為一個​<code>​date​</code>​:

使用date.parse()時傳入的字元串使用實際月份01~12,轉換為date對象後getmonth()擷取的月份值為0~11。

​<code>​date​</code>​對象表示的時間總是按浏覽器所在時區顯示的,不過我們既可以顯示本地時間,也可以顯示調整後的utc時間:

那麼在javascript中如何進行時區轉換呢?實際上,隻要我們傳遞的是一個​<code>​number​</code>​類型的時間戳,我們就不用關心時區轉換。任何浏覽器都可以把一個時間戳正确轉換為本地時間。

時間戳是個什麼東西?時間戳是一個自增的整數,它表示從1970年1月1日零時整的gmt時區開始的那一刻,到現在的毫秒數。假設浏覽器所在電腦的時間是準确的,那麼世界上無論哪個時區的電腦,它們此刻産生的時間戳數字都是一樣的,是以,時間戳可以精确地表示一個時刻,并且與時區無關。

是以,我們隻需要傳遞時間戳,或者把時間戳從資料庫裡讀出來,再讓javascript自動轉換為當地時間就可以了。

要擷取目前時間戳,可以用:

字元串是程式設計時涉及到的最多的一種資料結構,對字元串進行操作的需求幾乎無處不在。比如判斷一個字元串是否是合法的email位址,雖然可以程式設計提取​<code>​@​</code>​前後的子串,再分别判斷是否是單詞和域名,但這樣做不但麻煩,而且代碼難以複用。

正規表達式是一種用來比對字元串的強有力的武器。它的設計思想是用一種描述性的語言來給字元串定義一個規則,凡是符合規則的字元串,我們就認為它“比對”了,否則,該字元串就是不合法的。

是以我們判斷一個字元串是否是合法的email的方法是:

建立一個比對email的正規表達式;

用該正規表達式去比對使用者的輸入來判斷是否合法。

因為正規表達式也是用字元串表示的,是以,我們要首先了解如何用字元來描述字元。

在正規表達式中,如果直接給出字元,就是精确比對。用​<code>​\d​</code>​可以比對一個數字,​<code>​\w​</code>​可以比對一個字母或數字,是以:

<code>'00\d'</code>可以比對<code>'007'</code>,但無法比對<code>'00a'</code>;

<code>'\d\d\d'</code>可以比對<code>'010'</code>;

<code>'\w\w'</code>可以比對<code>'js'</code>;

​<code>​.​</code>​可以比對任意字元,是以:

​<code>​'js.'​</code>​可以比對​<code>​'jsp'​</code>​、​<code>​'jss'​</code>​、​<code>​'js!'​</code>​等等。

要比對變長的字元,在正規表達式中,用​<code>​*​</code>​表示任意個字元(包括0個),用​<code>​+​</code>​表示至少一個字元,用​<code>​?​</code>​表示0個或1個字元,用​<code>​{n}​</code>​表示n個字元,用​<code>​{n,m}​</code>​表示n-m個字元:

來看一個複雜的例子:​<code>​\d{3}\s+\d{3,8}​</code>​。

我們來從左到右解讀一下:

<code>\d{3}</code>表示比對3個數字,例如<code>'010'</code>;

<code>\s</code>可以比對一個空格(也包括tab等空白符),是以<code>\s+</code>表示至少有一個空格,例如比對<code>' '</code>,<code>'\t\t'</code>等;

<code>\d{3,8}</code>表示3-8個數字,例如<code>'1234567'</code>。

綜合起來,上面的正規表達式可以比對以任意個空格隔開的帶區号的電話号碼。

如果要比對​<code>​'010-12345'​</code>​這樣的号碼呢?由于​<code>​'-'​</code>​是特殊字元,在正規表達式中,要用​<code>​'\'​</code>​轉義,是以,上面的正則是​<code>​\d{3}\-\d{3,8}​</code>​。

但是,仍然無法比對​<code>​'010 - 12345'​</code>​,因為帶有空格。是以我們需要更複雜的比對方式。

要做更精确地比對,可以用​<code>​[]​</code>​表示範圍,比如:

<code>[0-9a-za-z\_]</code>可以比對一個數字、字母或者下劃線;

<code>[0-9a-za-z\_]+</code>可以比對至少由一個數字、字母或者下劃線組成的字元串,比如<code>'a100'</code>,<code>'0_z'</code>,<code>'js2015'</code>等等;

<code>[a-za-z\_\$][0-9a-za-z\_\$]*</code>可以比對由字母或下劃線、$開頭,後接任意個由一個數字、字母或者下劃線、$組成的字元串,也就是javascript允許的變量名;

<code>[a-za-z\_\$][0-9a-za-z\_\$]{0, 19}</code>更精确地限制了變量的長度是1-20個字元(前面1個字元+後面最多19個字元)。

​<code>​a|b​</code>​可以比對a或b,是以​<code>​(j|j)ava(s|s)cript​</code>​可以比對​<code>​'javascript'​</code>​、​<code>​'javascript'​</code>​、​<code>​'javascript'​</code>​或者​<code>​'javascript'​</code>​。

​<code>​^​</code>​表示行的開頭,​<code>​^\d​</code>​表示必須以數字開頭。

​<code>​$​</code>​表示行的結束,​<code>​\d$​</code>​表示必須以數字結束。

你可能注意到了,​<code>​js​</code>​也可以比對​<code>​'jsp'​</code>​,但是加上​<code>​^js$​</code>​就變成了整行比對,就隻能比對​<code>​'js'​</code>​了。

有了準備知識,我們就可以在javascript中使用正規表達式了。

javascript有兩種方式建立一個正規表達式:

第一種方式是直接通過​<code>​/正規表達式/​</code>​寫出來

第二種方式是通過​<code>​new regexp('正規表達式')​</code>​建立一個regexp對象。

兩種寫法是一樣的:

注意,如果使用第二種寫法,因為字元串的轉義問題,字元串的兩個​<code>​\\​</code>​實際上是一個​<code>​\​</code>​。

先看看如何判斷正規表達式是否比對:

regexp對象的​<code>​test()​</code>​方法用于測試給定的字元串是否符合條件。

用正規表達式切分字元串比用固定的字元更靈活,請看正常的切分代碼:

嗯,無法識别連續的空格,用正規表達式試試:

無論多少個空格都可以正常分割。加入​<code>​,​</code>​試試:

再加入​<code>​;​</code>​試試:

如果使用者輸入了一組标簽,下次記得用正規表達式來把不規範的輸入轉化成正确的數組。

除了簡單地判斷是否比對之外,正規表達式還有提取子串的強大功能。用​<code>​()​</code>​表示的就是要提取的分組(group)。

exec() 方法用于檢索字元串中的正規表達式的比對

比如:

​<code>​^(\d{3})-(\d{3,8})$​</code>​分别定義了兩個組,可以直接從比對的字元串中提取出區号和本地号碼:

如果正規表達式中定義了組,就可以在​<code>​regexp​</code>​對象上用​<code>​exec()​</code>​方法提取出子串來。

exec() 方法的功能非常強大,它是一個通用的方法,而且使用起來也比 test() 方法以及支援正規表達式的 string 對象的方法更為複雜。

​<code>​exec()​</code>​方法在比對失敗時傳回​<code>​null​</code>​。

​<code>​exec()​</code>​方法在比對成功後,會傳回一個​<code>​array​</code>​,第一個元素是正規表達式比對到的整個字元串,後面的字元串表示比對成功的子串。

                                                                            此數組的第 0 個元素是與正規表達式相比對的文本,第 1 個元素是與 regexpobject 的第 1 個子表達式相比對的文本(如果有的話),第 2 個元素是與 regexpobject 的第 2 個子表達式相比對的文本(如果有的話),以此類推。

除了數組元素和 length 屬性之外,exec() 方法還傳回兩個屬性。index 屬性聲明的是比對文本的第一個字元的位置。input 屬性則存放的是被檢索的字元串 string。我們可以看得出,在調用非全局的 regexp 對象的 exec() 方法時,傳回的數組與調用方法 string.match() 傳回的數組是相同的。

但是,當 regexpobject 是一個全局正規表達式時,exec() 的行為就稍微複雜一些。它會在 regexpobject 的 lastindex 屬性指定的字元處開始檢索字元串 string。當 exec() 找到了與表達式相比對的文本時,在比對後,它将把 regexpobject 的 lastindex 屬性設定為比對文本的最後一個字元的下一個位置。這就是說,您可以通過反複調用 exec() 方法來周遊字元串中的所有比對文本。當 exec() 再也找不到比對的文本時,它将傳回 null,并把 lastindex 屬性重置為 0。

提取子串非常有用。來看一個更兇殘的例子:

這個正規表達式可以直接識别合法的時間。但是有些時候,用正規表達式也無法做到完全驗證,比如識别日期:

對于​<code>​'2-30'​</code>​,​<code>​'4-31'​</code>​這樣的非法日期,用正則還是識别不了,或者說寫出來非常困難,這時就需要程式配合識别了。

需要特别指出的是,正則比對預設是貪婪比對,也就是比對盡可能多的字元。舉例如下,比對出數字後面的​<code>​0​</code>​:

由于​<code>​\d+​</code>​采用貪婪比對,直接把後面的​<code>​0​</code>​全部比對了,結果​<code>​0*​</code>​隻能比對空字元串了。

必須讓​<code>​\d+​</code>​采用非貪婪比對(也就是盡可能少比對),才能把後面的​<code>​0​</code>​比對出來,加個​<code>​?​</code>​就可以讓​<code>​\d+​</code>​采用非貪婪比對:

javascript的正規表達式還有幾個特殊的标志,最常用的是​<code>​g​</code>​,表示全局比對:

全局比對可以多次執行​<code>​exec()​</code>​方法來搜尋一個比對的字元串。當我們指定​<code>​g​</code>​标志後,每次運作​<code>​exec()​</code>​,正規表達式本身會更新​<code>​lastindex​</code>​屬性,表示上次比對到的最後索引:

 全局比對類似搜尋,是以不能使用​<code>​/^...$/​</code>​,那樣隻會最多比對一次。

正規表達式還可以指定  ​<code>​i ​</code>​标志,表示忽略大小寫, ​<code>​m ​</code>​标志,表示執行多行比對。

正規表達式非常強大,要在短短的一節裡講完是不可能的。要講清楚正則的所有内容,可以寫一本厚厚的書了。如果你經常遇到正規表達式的問題,你可能需要一本正規表達式的參考書。

寫一個驗證email位址的正規表達式。版本一應該可以驗證出類似的email:

驗證單個email輸入是否正确

驗證多個email輸入是否正确,可将輸入的email使用split拆分成數組,再循環從數組中取值進行比較測試

字元描述:

^ :比對輸入的開始位置。

\:将下一個字元标記為特殊字元或字面值。

* :比對前一個字元零次或幾次。

+ :比對前一個字元一次或多次。

(pattern) 與模式比對并記住比對。

x|y:比對 x 或 y。

[a-z] :表示某個範圍内的字元。與指定區間内的任何字元比對。

\w :與任何單詞字元比對,包括下劃線。

{n,m} 最少比對 n 次且最多比對 m 次

$ :比對輸入的結尾。 

 參考郵件校驗的正則 :https://www.jb51.net/article/72345.htm

json是javascript object notation的縮寫,它是一種資料交換格式。

在json出現之前,大家一直用xml來傳遞資料。因為xml是一種純文字格式,是以它适合在網絡上交換資料。xml本身不算複雜,但是,加上dtd、xsd、xpath、xslt等一大堆複雜的規範以後,任何正常的軟體開發人員碰到xml都會感覺頭大了,最後大家發現,即使你努力鑽研幾個月,也未必搞得清楚xml的規範。

終于,在2002年的一天,道格拉斯·克羅克福特(douglas crockford)同學為了拯救深陷水深火熱同時又被某幾個巨型軟體企業長期愚弄的軟體工程師,發明了json這種超輕量級的資料交換格式。

道格拉斯同學長期擔任雅虎的進階架構師,自然鐘情于javascript。他設計的json實際上是javascript的一個子集。在json中,一共就這麼幾種資料類型:

number:和javascript的​<code>​number​</code>​完全一緻;

boolean:就是javascript的​<code>​true​</code>​或​<code>​false​</code>​;

string:就是javascript的​<code>​string​</code>​;

null:就是javascript的​<code>​null​</code>​;

array:就是javascript的​<code>​array​</code>​表示方式——​<code>​[]​</code>​;

object:就是javascript的​<code>​{ ... }​</code>​表示方式。

以及上面的任意組合。

并且,json還定死了字元集必須是utf-8,表示多語言就沒有問題了。為了統一解析,json的字元串規定必須用雙引号​<code>​""​</code>​,object的鍵也必須用雙引号​<code>​""​</code>​。

由于json非常簡單,很快就風靡web世界,并且成為ecma标準。幾乎所有程式設計語言都有解析json的庫,而在javascript中,我們可以直接使用json,因為javascript内置了json的解析。

把任何javascript對象變成json,就是把這個對象序列化成一個json格式的字元串,這樣才能夠通過網絡傳遞給其他計算機。

如果我們收到一個json格式的字元串,隻需要把它反序列化成一個javascript對象,就可以在javascript中直接使用這個對象了。

讓我們先把小明這個對象序列化成json格式的字元串:

要輸出得好看一些,可以加上參數,按縮進輸出:

結果:

第二個參數用于控制如何篩選對象的鍵值,如果我們隻想輸出指定的屬性,可以傳入​<code>​array​</code>​:

還可以傳入一個函數,這樣對象的每個鍵值對都會被函數先處理:

上面的代碼把所有屬性值都變成大寫:

如果我們還想要精确控制如何序列化小明,可以給​<code>​xiaoming​</code>​定義一個​<code>​tojson()​</code>​的方法,直接傳回json應該序列化的資料:

拿到一個json格式的字元串,我們直接用​<code>​json.parse()​</code>​把它變成一個javascript對象:

​<code>​json.parse()​</code>​還可以接收一個函數,用來轉換解析出的屬性:

用浏覽器通路openweathermap的天氣api,檢視傳回的json資料,然後傳回城市、天氣預報等資訊:

var info = {

  city: data.city.name,

  weather: data.list[0].weather[0].main,

  time: data.list[0].dt_txt

};

alert(json.stringify(info, null, ' '));

});

JavaScript(四)标準對象

繼續閱讀