JS2

第五章*****************************************************************************************

什么是索引數組: 下標都是數字的數組

關聯數組:

什么是: 可自定義下標名稱的數組

為什么: 為了讓每個元素都有一個專門的名稱

好處: 1. 便于維護;2.快速查找

何時: 1. 希望每個元素都有明確的意義時

? ? ? 2. 快速定位想要的元素時

如何: 2件事(創建、訪問)

創建分2步:

??? 1. 先創建空數組:var arr=[];

??? 2.向空數組中添加新元素,要使用自定義的下標名稱

? ? ? ?EX:ym["name"]="楊冪"

? ? ? ? ? ?ym["math"]=81;

? ? ? ? ? ?ym["chs"]=59;

? ? ? ? ? ?ym["eng"]=89;

訪問: 用法和訪問索引數組完全一樣,同變量的用法,只不過要使用自定義的下標名稱

關聯數組中.length屬性失效,永遠等于0

因為關聯數組中沒有數字下標,length無法+1

遍歷關聯數組(鍵值對的集合): 只能用for( in )

for(var key in arr){? /*in:自動依次取出arr中每個下標名稱保存在變量key中;key:當前房間號:鍵*/

?arr[key]; ? ? ? ? ? ? ? //當前元素值: value,當前屬性名: key

} ? ? ? ? ? ? ? ? ? ? ? ?? /*強調: key不能加引號, 因為每次循環都在變化*/

索引數組:無法提前預知元素的具體位置,只能靠遍歷查找,受元素個數和元素存儲位置影響極大(慢)

關聯數組:直接通過下標定位元素位置,查找速度和元素個數及元素位置無關(快)

關聯數組原理:hash算法: 根據一個字符串,計算出盡量不重復的一個序號。相同的字符串計算出的序號一定相同,相同下標的值會覆蓋原先的值

向關聯數組中保存元素:

? ? 將自定義下標名交給hash算法,計算一個散列的位置序號。將元素保存到序號指定位置

從關聯數組中取值時:

? ? 將自定義下標名交給hash算法,計算出和存入時完全相同的序號,引擎直接去序號位置獲得元素

? ? 優點: 不受存儲位置和元素個數的影響

_______________________________________________________________________________________________

1. 數組API

什么是數組: 存儲多個數據,并提供了操作數據的API的對象

API: 別人已經實現的,咱們用現成的程序

將數組轉字符串有2種:

?String(arr): 將arr中每個元素都轉為字符串,用逗號連接

? ? 何時: 給數組拍照,查看數組的中間修改狀態,判斷操作前后數組是否發生了變化

?arr.join("自定義連接符"): 將arr中每個元素都轉為字符串,用自定義的連接符連接元素

? ? 何時: 只要不希望使用逗號連接符時

固定套路: 1. 把單詞拼接為句子

? ? ? ? ? 2. 無縫拼接:

? ? ? ? ? ?? 錯誤: arr.join() <=> String(arr) ?=>輸出為逗號連接

? ? ? ? ? ?? 正確: arr.join("")

? ? ? ? ? ?? 重要用途: 判斷數組是否為空

? ? ? ? ? 3.動態生成頁面元素(只會在元素之間添加連接符,所以要在arr.join("...")前后補全標簽)

? ? ? ? ? ? ?2步:①?var html="<ANY>"+arr.join("</ANY><ANY>")+"</ANY>";

? ? ? ? ? ? ? ? ? ? 或 var html="<ul>"+uls.join("")+"</ul>";

? ? ? ? ? ? ? ?? ② elem.innerHTML=html;

console.log(String(arr)),console.log(arr),console.dir(arr)

console.log(arr); 先輸出dir的結構,刷新后變為String(arr)

僅輸出內容,不關心結構: console.log(String(arr))

查看數組存儲結構: console.dir(arr) ? ? ? ? ? /*dir查看結果時,不遵循先后執行的順序*/

判斷數組中是否含有某個元素:

數組可用indexOf搜索某個元素的下標,返回在數組中找到的給定元素的第一個索引,若不存在,則返回-1,但數組元素需要完全相等(===)才會搜索成功,且不識別NaN

如: var arr = ['啦啦',2,4];

? ? arr.indexOf('啦');? ? //-1

? ? arr.indexOf('啦啦');? //0

使用ES6的擴展運算符(...)代替cancat,可以更方便的合并數組

如: var arr1 = [1,2,3];

? ? var arr2 = [4,...arr1,5];? ? //[4,1,2,3,5]

toLocaleString()可將數組中的每個元素用逗號(,)隔開,組成字符串(調用join()方法)

var?str = arr.toLocaleString()

_______________________________________________________________________________________________

拼接和選取: 都無權修改原數組,只能返回新數組對象

拼接: 將多個數組或元素,和當前數組拼接為一個新數組

? ? ? 如何:var newArr=arr1.concat(值1,值2,arr2,...);

? ? ? 強調: 1.不修改原數組,只返回新數組

? ? ? ? ? ? 2. 可打散數組類型的參數為單個元素,再拼接 ? ? ? ? ? /*concat獨有*/

? ? ? 注意:?若是大數組會消耗大量內存,可用arr1.push.apply(arr1, arr2)代替,將arr2合并到arr1中

選取: 復制原數組中指定開始位置到結束位置之間的多個元素,組成新數組———原數組保持不變

? ? ? 如何:var subArr=arr.slice(starti,endi+1);

? ? ? 強調: 1.不修改原數組,僅復制出想要的元素組成新數組

? ? ? ? ? ? 2.如果一個API的兩個參數都是下標時,就含頭不含尾

? ? ? 簡寫: 1. 如果參數位置離結尾近,可用負數下標:

? ? ? ? ? ? ?? arr.length-n 可簡寫為:-n(倒數第n個(不包含尾))(API自動加length)

? ? ? ? ? ? 2. 可省略第二個參數(-1),表示一直選取到結尾

? ? ? ? ? ? 3. 兩個參數都可省略: 完整復制一個數組(地址值不同)

_______________________________________________________________________________________________

兩個對象作比較(arr2==arr1):

不做任何轉換,直接比較兩個對象的地址值,用于判斷兩個變量是否引用同一個對象

引用類型的對象(arr2=arr1):用新變量修改對象,等效于直接修改原對象,新舊變量都受影響(地址值相同)

復制數組(地址值不同):①選取復制: var arr2=arr1.slice();

? ? ? ? ? ? ? ? ? ? ? ②復制索引數組:for(var?i=0;i<arr2.length;i++){arr2[i]=arr1[i]};

? ? ? ? ? ? ? ? ? ? ? ③復制關聯數組:for(var key in arr1){key; arr2[key]=arr1[key]};

_______________________________________________________________________________________________

修改數組: splice(強調: 直接修改原數組)

刪除元素:arr.splice(starti,n)

? 刪除starti位置開始的n個元素

? 強調: 不必考慮含頭不含尾(n是個數)

? 其實有返回值: 返回被刪除的元素組成的臨時數組

? ??var deletes=arr.splice(starti,n);? ? ? ? ? ? /*deletes保存了刪除的元素*/

? 簡寫: 1. 支持負數下標,表示倒數第n個(自動用length-n)

? ? ? ? 2. 省略n(從starti 刪到結尾)

插入新元素:arr.splice(starti,0,值1,值2,...)? ? ? ?//刪除0個

? ? 在starti位置插入新的值1,值2,...

? ? 強調: 1.原starti位置的值及其之后的值被向后順移

? ? ? ? ? 2.不支持打散數組類型參數(如果插入一個數組,將變成二維數組)

替換:?arr.splice(starti,n,值1,值2,...)

? ? 先刪除舊的,再在同一位置插入新的

? ? 先刪除starti開始的n個元素,再在starti位置插入值1,值2,...

? ? 強調: 刪除的個數和插入的個數不必相同

翻轉: ?arr.reverse();

_______________________________________________________________________________________________

排序:

什么是: 將數組中的元素按從小到大或從大到小的順序重新排列

何時: 任何數據在給用戶展示前,必須先排序

如何:arr.sort(); ? ? ? ? ? ? /*將 arr 數組按字符串升序,直接修改原數組*/

? 原理: 將所有元素都轉為字符串,再按字符串升序排列

? 何時: 只有按字符串升序排列時,才用默認的sort()

問題: 只能按字符串升序排列

解決:自定義比較器函數:

? 什么是: 專門比較任意兩值大小的函數

? 何時: 如果sort默認的排序規則不是想要的,可自定義比較器代替sort中默認的排序規則

要求: 2個參數: a,b

返回值: 如果a>b,就返回正數

? ? ? ? 如果a<b,就返回負數

? ? ? ? 否則返回0

最簡單的數字升序比較器

function cmp(a,b){return a-b;}; ? ? ? /*定義比較器函數*/

arr.sort(cmp); ? ? ? ? ? ? ? ? ? ? ? ?/*傳入sort()中*/

簡化為:arr.sort(function(a,b){return a-b});? ?/*cmp=function(a,b){return a-b;}*/

? ? ? ? ? ? ? /* 對對象的值進行排序: arr.sort(function(a,b){ return obj[a]-obj[a] }) */

如何使用: 將比較器函數對象作為參數傳入sort()函數中

強調:不加()? ? ? ? ? ? ?/*cmp: 回調函數callback,不加()*/

回調函數:自己定義的函數,自己不調用,不只調用一次,而是傳入另一個函數中,被另一個函數反復調用

何時: 只要對數字元素排序,都要自定義比較器函數

遞歸調用:函數內又調用了自己(效率極低,幾乎所有的遞歸都可用循環代替)

問題2: 如何降序:

解決: 只要顛倒比較器結果的正負號,就可改升序為降序

最簡單的數字降序比較器

function cmp(a,b){return b-a};

arr.sort(cmp);

簡化為: arr.sort(function(a,b){return b-a});

_______________________________________________________________________________________________

2. 棧和隊列

說明: js中沒有專門的棧和隊列結構,都是用普通數組模擬的

棧stack:

什么是棧: 一端封閉,只能從另一端進出的數組

? ? ? ? ? 棧是限定僅在表頭/表尾進行插入/刪除操作的線性表

何時: 只要希望始終使用最后進入數組的新元素時(先進后出)

如何:

? 1. 結尾出入棧:

????結尾入棧: arr.push(值)<=> ?arr[arr.length]=值?? /*在末尾追加一個新值*/

? ?? 強調: 1. 其實push可壓入多個值: arr.push(值1, 值2)

? ? ? ? ?? 2. 不支持打散數組參數 ? ? ? ? ? ? ? ? ? ? //可用來創建二維數組

????結尾出棧: var last=arr.pop();? ? ? ? ? ? ? ? ? ?/*移出數組末尾的最后一個元素*/

? 2. 開頭出入棧:

????開頭入棧: arr.unshift(值)? ? ? ? ? ? ? ? ? ? ? ? /*在開頭插入一個值*/

? ?? 強調: 開頭入棧后的元素順序和結尾入棧后的元素順序是相反的

????開頭出棧: var first=arr.shift();? ? ? ? ? ? ? ?/*移出數組開頭的第一個元素*/

隊列queue:

什么是: 只能從結尾進入,從開頭出的數組,是事件循環(Event Loop)的基礎結構

何時: 只要希望按照先來后到的順序使用數組元素時

如何: 1. 從結尾入隊列:arr.push(值);

? ? ? 2. 從開頭出隊列:var first=arr.shift();

堆:

堆數據結構是一種樹狀結構,它使用key-value的形式存儲,是無序的

變量的存放:

基本數據類型:?保存在棧內存中,占有固定大小的空間,通過按值來訪問

引用類型:?保存在堆內存中,因為值的大小不固定,所以不能保存到棧內存中,但內存地址大小是固定的,可以保存在棧內存中。當查詢引用類型的變量時,先從棧中讀取內存地址,然后通過內存地址找到堆中的值,一般叫做按引用訪問

_______________________________________________________________________________________________

總結: 向數組中添加元素4種:

1. concat():①不修改原數組,返回新數組

? ? ? ? ? ?? ②在結尾拼接元素

? ? ? ? ? ?? ③支持打散數組類型參數,另一個是.apply(),只有這兩個能打散數組

2. splice():①直接修改原數組

? ? ? ? ? ?? ②在任意位置插入新元素

? ? ? ? ? ?? ③不支持打散數組類型參數

3. push():①直接修改原數組

? ? ? ? ?? ②只能在結尾拼接元素

? ? ? ? ?? ③不支持打散數組類型參數

4. shift():①直接修改原數組

? ? ? ? ? ? ②只能在開頭拼接元素

? ? ? ? ? ? ③不支持打散數組類型參數

取出數組元素: 4種:

1. slice():①可獲取任意位置的任意個元素

? ? ? ? ? ? ②不修改原數組,返回選中的元素組成的新數組

2. splice():①刪除任意位置的任意個元素

? ? ? ? ? ?? ②直接修改原數組

? ? ? ? ? ?? ③返回被刪除的元素組成的新數組

3. pop():只能從結尾刪除一個元素,并返回

4. shift():只能從開頭刪除一個元素,并返回

_______________________________________________________________________________________________

3.二維數組

什么是: 數組中的元素,又引用了另一個子數組

何時:

? 1. 保存橫行豎列的二維數據

? 2. 一個大的數組中,還需要對元素進行更細致分類

如何創建: 2種:

1. 先創建空數組,再添加子數組:

var arr=[];

? arr[0]=[0,0,0,0];

? arr[1]=[0,0,0,0];

? ...

2. 創建數組同時,初始化子數組

var arr=[

? [0,0,0,0],

? ... ,

? [0,0,0,0]

];

訪問:arr[r][c](r行號,c列號)? 用法和普通數組的元素及變量完全一樣

越界: 二維數組的行下標r,不能越界,越界報錯

遍歷二維數組:

for(var r=0;r<data.length;r++){ ? ? ? ? //外層循環控制行

? for(var c=0;c<data[r].length;c++){ ? ?//內層循環控制列

? ? data[r][c] ? ? ? ? ? ? ? ? ? ? ? ?? //獲得當前元素

}?}

創建二維數組:

var arr=[];

for (var i=0;i<N;i++ ){

? arr[i]=[]; ? ? ? ? ? ? ? ?//創建一個二維數組,內容為空

? for (var j=0;j<M;j++){? ? //為二維數組賦值 或填充n個空元素: arr1[i]=new Array(n);

? arr[i][j]=0;

} }

冒泡排序算法(一維數組):

function bubblesort(arr){

? for(varr=1;r<arr.length;r++){ ? ? ? ? //外層循環控制輪數

? ? for(vari=0;i<arr.length-r;i++){ ? ? //內層循環控制每輪中的比較次數

? ? ? if(arr[i]>arr[i+1]){ ? ? ? ? ? ? ? //如果i位置的值>i+1位置的值

? ? ? ? arr[i]^=arr[i+1]; ? ? ? ? ? ? ? ?//交換兩位置的值

? ? ? ? arr[i+1]^=arr[i];

? ? ? ? arr[i]^=arr[i+1];

} } } }

第六章*****************************************************************************************

三、String類型

什么是: 由多個字符組成的"只讀"字符數組

String API: 強調: 所有String API都無權修改原字符串,只能返回新字符串

VS 數組: 相同:?1. 下標;如:str[1] ? ?2. .length

? ? ? ? ? ?? 3.var subArr=arr.slice(starti,endi+1);(選取,無權修改原數組)

? ? ? ?? 不同: 類型不同, API不通用

內置對象: ES標準中規定的,瀏覽器廠商已經實現的對象

包括11個:

? String? Number? Boolean? ————— ?這3個是包裝類型

? Array ? Date ? ?Math ? RegExp

? Error

? Function ?Object

? Global (在瀏覽器中被window代替)

包裝類型

什么是:專門包裝原始類型的值,并提供操作原始類型值的API

為什么: 原始類型的值本身不具有任何功能,才需要包裝類型對象的幫助,完成功能

何時: 一般不必手動使用

? ? ? 只要試圖用原始類型的值調用函數時,都會自動創建包裝類型的對象,調用對象的函數執行操作

注意: 只要引用了字符串的屬性(.屬性),字符串就會通過調用new String(str)的方式轉換成對象,這個對象繼承了字符串的方法,并被用來處理屬性的引用,一旦屬性引用結束,這個新創建的對象就會銷毀(實質上并不一定創建和銷毀,但整個過程看起來是這樣的)

比如: n.toFixed(2) => ?typeof n => ?number

? ? ? <=>new Number(n).toFixed(2)

?? str.charCodeAt() =>typeof str =>string

?? <=>new String(str).charCodeAt()

大小寫轉換

將字符串中所有字母,統一轉為大寫或小寫

str.toLowerCase() ? ? ? ?? 轉小寫

str.toUpperCase() ? ? ? ?? 轉大寫

何時: 不區分大小時,都要先轉為一致的大小寫,再比較或判斷:?驗證碼,用戶名,電子郵件

獲得指定位置的字符:?str.charAt(i)? =>? str[i]

獲得指定位置字符的unicode號:?str.charCodeAt(i) ? ? ?? 獲得str中i位置的字符的unicode號

將unicode號,反向轉回文字: ? String.fromCharCode(unicode號) ?? 一次只能轉一個字,要用循環

獲取子字符串:3種

str.slice(starti, endi+1)

str.substring(starti, endi+1) ?? 用法同slice,但不支持負數參數(負數自動轉為0,取較小的值作為開始位置)

str.substr(starti, n)? ? ? ? ? ? ? ? 從starti開始,獲取n個字符,n是個數,省略則到結尾為止

_______________________________________________________________________________________________

查找關鍵詞: 4種:

1. 查找一個固定關鍵詞的位置(僅查找規則內的第一個)

var i=str.indexOf("關鍵詞",fromi)

? 在str中fromi位置之后,查找下一個"關鍵詞"的位置

返回值: 找到的關鍵詞的下標位置i

? ? ? ? 如果沒找到,返回-1

? 簡寫: 省略fromi,默認從0開始

var i=-1;

do{

? i=str.indexOf("關鍵詞",i+1);

? if(i!=-1)

? ? console.log("在位置"+i+"發現關鍵詞");

? else break;

}while(true);

2. 查找最后一個關鍵詞的位置

var i=str.lastIndexOf("關鍵詞");

用于獲取文件的擴展名(取最后一個.后的剩余字符串)

indexOf的問題: 只能查找一個固定關鍵詞的位置

解決: 正則表達式模糊匹配多種關鍵詞

3. 判斷字符串中是否包含符合規則的關鍵詞

var i=str.search(/reg/i) ?? /*reg: 正則表達式,在str中找到第一個符合正則要求的敏感詞的位置*/

返回值: 返回關鍵詞的下標位置i

? ? ? ? 如果沒找到返回-1

? 問題: 正則表達式默認都是區分大小寫的

? 解決:在第二個/后加i,表示忽略(ignore)大小寫

? 何時: 只要僅判斷有沒有關鍵詞時,首選search

? 問題: 1. 只能查找第一個關鍵詞,無法找所有

? ? ? ? 2. 僅返回位置,無法返回關鍵詞內容

4. 查找所有關鍵詞的內容

var kwords=str.match(/reg/ig); ? ? ? ?//也可使用字符串,結果為查找到的字符串

返回值: 返回所有關鍵詞組成的數組

? ? ? ? 如果沒找到,返回null

使用正則時: 數組的第一個元素(下標為0)表示第一個分組,下標為2的是第二個分組

使用/g時: 下標為0的是找到的第0個分組,下標為1的是第一個分組,下標為2的是第二個分組

使用字符串時,下標為0的是找到的字符串,index是下標,input是要查找的字符串

? 問題: 正則表達式默認只匹配第一個符合條件的敏感詞

? 解決:在第二個/后加g,表示查找全部(global)

? 何時: 僅希望獲得關鍵詞內容時

? 問題: 只能獲得內容,無法獲得每個敏感詞的位置

? 解決: 查找每個關鍵詞內容,又查找位置: regExp.exec()

_______________________________________________________________________________________________

替換: 將字符串中找到的關鍵詞,替換為指定的新內容(2種), (無權修改原字符串,只能返回新字符串)

1. 簡單替換: 將所有關鍵詞都替換為同一種新值

str=str.replace(/reg/ig,"新值");

2. 高級替換: 根據每個關鍵詞的不同,動態選擇替換不同的新值

str=str.replace(/reg/ig,function(kw){ ? ? ?/*回調函數,kw 自動獲得本次找到的關鍵詞*/

? return ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? /*根據不同的kw,動態返回不同的值*/

})

衍生:刪除: 將關鍵詞替換為""

str=str.replace(/reg/ig,"")

str.replace(/(^\s+)|(\s+$)/g, "") ? ? ? ? //去掉字符串首尾的空字符

切割: 按指定關鍵字,將一個字符串切割為多段子字符串(2種)

返回: 返回的是多個子字符串組成的數組,切割后的結果中,不包含分隔符

注意:當分隔符不為空字符("")時,分隔符在邊界或連續出現兩個時,會形成一個空字符

? ? ?分隔符的個數 = str.split("分隔符").length-1? ?//字符串分隔后組成的數組長度-1

1. 簡單: 分隔符是固定的:

var subStrs=str.split("分隔符") ? ? ? ? ? ?//不修改原字符串

2. 復雜: 分隔符不是固定的:

var subStrs=str.split(/reg/i);

固定套路: 將字符串打散為字符數組: var chars=str.split("");

多字符切割: var newStr = oldStr.split(/\:|\./g);

? ? ? ? ? ? var newStr = oldStr.split(/[共]|[注]|[元]/g);

function zhao(str){ ? ? ? ? //查找一個字符串中每個字符連續出現的次數

? var arr1=str.split("");

? arr1.sort(); ? ? ? ? ? ?? //查找一共出現的次數用arr.sort()先排序再查找

? for(var i=0,j=1;i<arr1.length;i++){

? ? if(arr1[i]===arr1[i+1]){

? ? ? j++;

? ? }else{

? ? ? console.log(arr1[i]+":"+j);

? ? ? j=1;

}?}?}

//截取url的后lastNum*2個字段

function getUrlInfo(lastNum){

var infoArr = location.href.split(/\?|\/|\&|\=/g);

? var arr = infoArr.slice(-lastNum*2);

? var result = new Object();

? for(var i=0; i<arr.length; i+=2){

? ? result[arr[i]] = arr[i+1];

? }

? return result;

}

_______________________________________________________________________________________________

正則表達式:Regular Expression

什么是: 規定一個字符串中字符出現規律的規則

何時:2種:?1.模糊查找多種關鍵詞

? ? ? ? ? 2.驗證用戶輸入的格式

如何:

1.最簡單的正則表達式,就是關鍵詞原文本身

2.字符集

什么是: 規定一位字符 備選字符列表 的集合

何時: 只要一位字符,有多種可能備選時

如何:[備選字符列表]? ? ? ? ? ? ? ? ? ? ? ? //?表示選擇其中之一

強調: 中間不要加逗號(,)

? ? ? 一個字符集([])只能規定一位字符的備選字

簡寫: 如果字符列表中 部分備選字符的unicode是連續的,可用-省略中間字符

比如:?[0-9] ? ? ? ? ? ?? 一位數字

? ? ? [a-z] ? ? ? ? ? ?? 一位小寫字母

? ? ? [A-Z] ? ? ? ? ? ?? 一位大寫字母

? ? ? [A-Za-z] ? ? ? ? ? 一位字母

? ? ? [0-9A-Za-z] ? ? ?? 一位字母或數字

? ? ? [\u4e00-\u9fa5] ? ?一位漢字

特殊:[^字符列表] ? ? ?? 除了××

3.預定義字符集

什么是: 對常用特定字符集的更簡化寫法:4個:

? \d ? ? ?? 一位數字 ?=> [0-9]

? \w ? ? ?? 一位字母,數字或_ ?=> [0-9A-Za-z_]

?\s ? ? ? 一位空字符: 空格,Tab...

?.? ? ? ? 通配符(匹配除回車、換行\n\r外的任意字符)

? \D? ? ? ? 類似[^0-9],非數字

? \W? ? ? ? 類似[^0-9A-Za-z_],除\w外的符號

? \S? ? ? ? 非\s的所有內容

\***: 是轉義字符,表示引用符 ? 比如: \. ?匹配點字符 ? \$匹配美元符號

空字符和空字符串不一樣,空字符用|表示

4.量詞

什么是: 規定一位字符集出現次數的規則

何時: 只要規定一位字符集出現的位數/次數

如何: 量詞必須緊跟在修飾的字符集之后,用來修飾相鄰的前一個字符集

包括: 2大類:

? ① 有明確數量邊界的:

? ?? 字符集{n,m} 至少n個,最多m個

? ?? 字符集{n,} ?至少n個,多了不限

? ?? 字符集{n} ? 必須n個

? ② 沒有明確數量邊界的:

? ?? 字符集? ? 可有可無,最多1個

? ?? 字符集* ? 可有可無,多了不限

? ??字符集+? ?至少一個,多了不限

5.選擇和分組

選擇:或

何時: 只要在多個規則中,任選其一匹配時

? 規則1|規則2|規則三...? (只要滿足3個規則之一即可) ?? /*|在正則中,優先級最低*/

分組: 用()將多個規則分為一組

何時: 只要希望一個量詞同時修飾多個字符集時,就要先將多個字符集分為一組(),再用量詞修飾分組

為什么: 默認字符集僅修飾相鄰的前一個字符集

比如: ??var reg=/(\d{2})\/(\d{2})\/(\d{4})/g; ? ?//將'07/29/2017'分為3組

反向引用:

var str = '2017-07-29'.replace(/(\d{4})-(\d{2})-(\d{2})/g, '$2/$3/$1'); ?//str: 07/29/2017

忽略分組: 不希望捕獲某些分組,只需要在分組內加上?:即可

var str = '2017-07-29'.replace(/(?:\d{4})-(\d{2})-(\d{2})/g,'$2/$1'); ? ? //str: 29/07

$1~$9存放著正則表達式中最近的9個正則表達式的提取結果,這些結果按照子匹配的出現順序依次排列

語法: RegExp.$n

這些屬性是靜態的,除了replace中的第二個參數可以省略RegExp外,其它地方使用都要加上RegExp

身份證號: 15位數字? 2位數字? 1位數字或Xx? /*后兩部分,可有可無,最多1次*/

? ? reg = \d{15} ?? (\d\d ? [0-9Xx]) ? ? ?

reg = /(^[1-9]\d{5} ?(18|19|([23]\d))\d{2} ?((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31) ?\d{3}[0-9Xx]$)|(^[1-9]\d{5} ?\d{2} ?((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31) ?\d{2}$)/

手機號: +86或0086 ? ? 可有可無,最多一次

???????? 空格 ? ? ? ? 可有可無,多了不限

???????? 1

???????? 3,4,5,7,8 ?? 選一個

???????? 9位數字

??? (\+86|0086)?\s*1[34578]\d{9}

reg = /^0?(13[0-9]|14[57]|15[012356789]|17[013678]|18[0-9])\d{8}$/

微 信 wei xin w x

? ? (微|w(ei)?)\s*(信|x(in)?)

6.指定匹配位置:3種:

?^字符串開頭,比如: 字符串開頭的空字符:^\s+

?$字符串結尾,比如: 字符串結尾的空字符:\s+$

? ? ? ? ? ? ? ? 比如: 開頭或結尾的空字符:^\s+|\s+$

?\b單詞邊界:包括: ?^$ 空格 標點符號,比如: 查找單詞no,匹配單詞no:?\bno\b

純英文格式電子郵件: var reg = /^[0-9A-Za-z_-]+@[0-9A-Za-z_-]+(\.[0-9A-Za-z_-]+)+$/

銀行卡: 借記卡、儲蓄卡19位, 貸記卡、信用卡16位, 存折17位

? \B?非單詞邊界

var reg = /([a-z])\1*/ig;?? //定義正則表達式變量

var reg =new RegExp("^[a-zA-Z]{9,20}$");

var kw = str.match(reg);? ? //使用此變量時,不需使用斜杠

判斷是否是圖片(帶參數):? /\.(png|jpe?g|gif|svg)(\?.*)?$/.test(str)

判斷是否是視頻(帶參數):? /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/.test(str)

_______________________________________________________________________________________________

/([a-z])\1*/ ? ? ? ?//表示: ?第一位必須是小寫字母,\1表示匹配和第一個()中完全相同的內容

? ? ? ? ? ? ? ? ? ? ? ? ? ?? *表示可有可無,多了不限,就算沒有和它匹配的也選擇它

? ? ? ? ? ? ? ? ? ? ? ? ? ? ?+表示至少一個,多了不限,有一個和它匹配的才選擇它

當 ? 緊跟在任何一個其他限制符(* ?+ ?? ?{n} ?{n,}? {n,m})后面時,匹配模式是非貪婪的,會盡可能少的匹配所搜索的字符串

默認的貪婪模式則盡可能多的匹配所搜索的字符串

? ? 例如: ?對于字符串"oooo","o+"將盡可能多的匹配"o",得到結果 ['oooo'],而 "o+?"?將盡可能少的匹配"o",得到結果 ['o','o','o','o']

m? 多行,將開始和結束字符(^和$)視為在多行上工作,也就是分別匹配每一行的開始和結束(由 \n 或 \r 分割),而不只是只匹配整個輸入字符串的最開始和最末尾處

s? 與m相反,單行匹配

第七章*****************************************************************************************

四、RegExp類型

什么是: 專門封裝一條正則表達式,并提供使用正則表達式執行查找和驗證的API

何時: 1. 使用正則表達式驗證用戶輸入的字符串格式

? ? ? 2. 即查找關鍵詞內容,又查找關鍵詞位置

如何:

創建: 2種

① 直接量(字面量)

var reg=/正則/ig;? ? ? ? ? ?? //i: 忽略(ignore)大小寫;g: 查找全部(global)

何時: 如果正則表達式是固定不變的

強調: //之中不支持js表達式,不支持動態生成正則表達式,如果再出現/,就必須改為\/

②?使用正則表達式的構造函數

var reg=new RegExp("正則","ig");

如: var reg=new RegExp("^[a-zA-Z]","g")? ? ?//使用引號時,不加斜杠

? ? var reg=new RegExp(/^[a-zA-Z]/,"gi")? ? //有斜杠時,不加引號

何時: 如果正則表達式需要動態拼接生成

強調: ""中再出現\或",都要改為\\和\"

API: 2個

① 即查找內容,又查找位置

var arr=reg.exec(str) ? ? ? ? /*在str中依次查找下一個符合reg規則的關鍵詞的內容和位置*/

返回值: 返回一個數組arr: 與正則表達式匹配的文本,后面依次為各個子表達式()的文本,用逗號分隔

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?最后一個arr["input"] 是要查找的內容str

? ? ? ?arr[0]本次找到的關鍵詞的內容

? ? ? ?arr["index"]本次找到的關鍵詞的下標位置

? ? ? ? 如果沒找到,就返回null

問題: 每次只返回本次找到的一個關鍵詞

解決: 用循環反復調用reg.exec

原理: 每次調用exec,做3件事:

? ?? 1. 將本次找到的關鍵詞保存在arr的0位置

? ?? 2. 將本次找到的關鍵詞位置保存在arr的index位置

? ?? 3. 每個reg對象都有一個.lastIndex屬性, 標識下次開始的查找位置,開始時為0

? ? ? ? 每執行完一次exec,exec會自動修改為:?reg.lastIndex=當前位置index+關鍵詞長度

function cha(str){

? var? reg=/./g; ? ? ? ? ? ? ? ? ? ? //在全局查找關鍵詞

? for(var i=0;i<str.length;i++){ ? ? //str.length: 字符串的長度

? ? var arr=reg.exec(str);

? ? console.log(arr[0]); ? ? ? ? ? ? //關鍵詞的內容

? ? console.log(reg.lastIndex-1);? ? //關鍵詞的下標位置

}?}

② 驗證字符串的格式

var bool=reg.test(str);? ? ? ? ? ? ? ?/*驗證str是否符合reg的規則要求*/

驗證通過返回true,不通過返回false,可直接當做判斷條件

問題: test默認只要部分匹配就返回true

解決:從頭到尾完全匹配(驗證),必須在正則表達式中: 前加^,后加$

_______________________________________________________________________________________________

五、Math類型

什么是: 專門保存數學計算的常量和函數的對象 的API

何時: 只要進行數學計算

如何:

創建: Math不用創建,不能new,直接使用

? ?? 所有常量和API都用Math直接調用

API

取整: 3種:

1.上取整: 只要超過,就取下一個整數

Math.ceil(num)

2.下取整: 只要超過,就省略小數部分

Math.floor(num)

Math.floor(num) ? VS ? parseInt(str)

只能對純數字 ? ? ? ? ? 能先去掉數字之后的非數字字符,再取整

3.四舍五入取整

Math.round(num)

Math.round ? ? ? ? ? ? ?? VS ? ? ? ? ?? n.toFixed(d)

缺: 只能取整,不能指定小數位數 ? ? ?? 優: 可指定任意小數位數四舍五入

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?金錢: Number(parseFloat(num).toFixed(2))

優:?將返回number,可直接計算? ? ? ? ? 缺: 將返回字符串類型,需要先轉換為數字類型,再計算

可自定義round函數

4. 乘方和開平方

Math.pow(底數,冪); ?? 乘方

Math.sqrt(n); ? ? ? ? 開平方

5. 最大值和最小值

Math.max(值1,值2,值3,...)

Math.min(值1,值2,值3,...)

問題: max/min不支持獲得數組中的最大/小值,求出數組中的最大/最小值

解決:Math.max.apply(null,arr)? ? ? ? ?/*apply: 調用,可自動打散數組類型參數*/

6. 隨機數

Math.random() ? ? ? ?? 取值: 0~1,默認得到一個隨機小數

公式:在任意[min,max]之間生成一個隨機整數:var r=parseInt(Math.random()*(max-min+1)+min)

簡寫: 如果min=0,即[0, max]之間: var r=parseInt( Math.random()*(max+1) )

例: 隨機數組中的數:var index = parseInt(Math.random()*arr.length)

_______________________________________________________________________________________________

六、Date類型

什么是: 專門封裝一個時間點,并提供操作時間的API

何時: 只要存儲時間或者計算時間

如何:

創建: 4種

1. 創建日期對象,并自動獲得當前系統時間

var now=new Date();//強調: 只能獲得客戶端本地時間,標準格式,即格林尼治標準時(GMT)

2. 創建日期對象,并封裝自定義時間點

var date=new Date("yyyy/MM/dd hh:mm:ss");? /*字符串中的月份為自動-1后的值*/

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?? //時間格式也可為: '2017-12-30 21:15:00'

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?? //或: 2018-03-06T17:12(部分瀏覽器有時差問題)

部分手機(如iPhone)獲取時間的方式與其它瀏覽器不同,需要兼容處理:

new Date("2017-02-05 12:10:10.12")可能會發生錯誤,函數返回錯誤是"Invalid Date"

var str = "2018-04-13 22:45:00";

var arr = str.split(/[- : \/]/);

var date = new Date(arr[0], arr[1]-1, arr[2], arr[3], arr[4] || '00', arr[5] || '00');

因為iOS不能識別 - 形式,也可以替換為斜杠形式:

date = date.replace(/-/g, '/');? ? // 2018/06/03 00:00:00

若不是字符串: var date=new Date(yyyy, MM-1,dd,hh,mm,ss);

如果只關心日期,不關心時間,后半部分時分秒可省略。省略后,默認是00:00:00

3. 用毫秒數創建日期對象

原理: 日期對象中保存的是1970年1月1日0點至今的毫秒數———整數

為什么: 時間段,不受時區影響

? ? ?? 相同的毫秒數: 在不同時區可顯示不同的時間點

總結: 將來數據庫中保存的時間都是毫秒數,不要用文字

何時: 只要將毫秒數轉化為當地時間格式時

var ms=date.getTime(); ? ? ? ? ? /*將標準格式的date轉化為毫秒數 ms*/

var now=new Date().getTime();? //獲取客戶端1970年1月1日0點至今的毫秒數(縮寫),時間戳

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?//注意時區問題

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?// +new Date()、Date now()? ? 返回毫秒數

var date1=new Date(ms); //將毫秒數?ms 轉化為操作系統當前所在時區的對應時間(必須是Number類型)

4. 復制一個日期對象:

為什么: 日期的計算只能直接修改原日期對象

后果: 計算后,無法保存計算前的原日期

何時: 如果用戶希望同時保留計算前后的開始時間和結束時間時,都要先將開始時間復制一份,再用副本計算結束時間

如何:

var date2=new Date(date1);

_______________________________________________________________________________________________

API: 3句話:

1. 8個單位: FullYear年 ? Month月 ? Date日 ? ? Day星期 ? ? ? ? ? ?———沒有s

? ? ? ? ? ?Hours小時? Minutes分鐘 ?Seconds秒 ?Milliseconds毫秒 ? ———都以s結尾

2. 每個單位都有一對兒getXXX()/setXXX()方法

? ?getXXX()? ?負責獲得指定單位上的數值

??setXXX(n) ?? 負責修改指定單位上的數值,可自動調整時間進制

?? 特例: Day(星期)沒有setXXX()方法

3. 取值范圍:除date(從1開始,31結束)外,其余都是從 0 開始到進制減 1 結束

?? FullYear: ? ? ? ? ? ? ? ? ? 和現實中年份一致

?? Month: 0~11 ? ? ? ? ? ? ?? 現實中: 1~12,計算機中的月份值比現實中少1,需要修正

?? Date: 1~31 ? ? ? ? ? ? ? ? 和現實一樣

?? Day: 0~6 ? ? ? ? ? ? ? ? ? 現實: 日~六,和現實中一致

?? Hours: 0~23 ? ? ? ? ? ? ? ?和現實一樣

?? Minutes/Seconds: 0~59 ? ? ?和現實一樣

_______________________________________________________________________________________________

日期計算

1. 兩日期對象可相減: 結果是毫秒差(ms),可用于倒計時

2. 對任意單位做加減:3步:

? ①取值: var date1=now.getDate();

? ②做加減: date1+=30;

? ? ? ? ? ? ?例如: 16+30=46

? ③放回去: now.setDate(date1); ? ? ? ? ? ?/*setDate可自動調整進制*/

簡寫:now.setDate(now.getDate()+n);

問題: setDate直接修改原日期對象,無法保留開始時間

解決: 在計算前,都要先將開始時間復制一個副本,再用副本計算結束時間

倒計時:

now/=1000, end/=1000;

放在定時器中:

now++;

varT?= parseInt((end-now)/1000);? ? ?//共剩多少時間(單位:秒)

var d = parseInt(T/(3600*24));? ? ? ? //剩多少天

var h = parseInt(T%(3600*24)/3600);? ?//剩多少小時

var m = parseInt(T%(3600)/60);? ? ? ? //剩多少分鐘

var s =T%60;? ? ? ? ? ? ? ? ? ? ? ? ?//剩多少秒

日期格式化(new Date()系統時間,轉字符串)

date.toString() ? ? ? ? ? ? ? 返回當地時間格式的完整版本(系統時間格式)

date.toLocaleString() ? ? ? ? 返回當地時間格式的簡化版本(有時分秒),不同平臺有可能不一樣

date.toLocaleDateString() ? ? 僅保留了日期部分

date.toLocaleTimeString() ? ? 僅保留了時分秒部分

date.toGMTString() ? ? ? ? ? ?獲得 0 時區的國際標準時間

_______________________________________________________________________________________________

new Date($.ajax({async: false}).getResponseHeader("Date")); ? ?//獲取服務器相應頭附帶的時間

輸出客戶端時間:

var weeks=["星期日","星期一","星期二","星期三","星期四","星期五","星期六"];

function fillTime(time){?return time>=10?time:"0"+time;?} ? ?//補全時間

var now = new Date();

var day = now.getDay();

var year ? ?=?now.getFullYear();? ? ? ? ? ? ?//年份

var month ? = fillTime(now.getMonth()+1);? ? //月份

var date ? ?= fillTime(now.getDate());? ? ? ?//日期

var hours ? = fillTime(now.getHours());? ? ? //小時

var minutes = fillTime(now.getMinutes());? ? //分鐘

var seconds = fillTime(now.getSeconds());? ? //秒

var dateTime=year+'-'+month+'-'+date+' '+hours+':'+minutes+':'+seconds+'('+weeks[day]+')';

console.log(dateTime); ? ?//2017-09-02 13:21:06(星期六)

const formatNumber = n =>{

? n = n.toString()

? return n[1] ? n : '0' + n

}

const formatTime = date =>{

? const year = date.getFullYear()

? const month = date.getMonth() + 1

? const day = date.getDate()

? const hour = date.getHours()

? const minute = date.getMinutes()

? const second = date.getSeconds()

? return [year, month, day].map(formatNumber).join('/') + ' ' + [hour, minute, second].map(formatNumber).join(':')

}

獲取相鄰的一段天數:

var base = +new Date(2018, 1, 1);? ? ? ? //獲取時間的毫秒數

var oneDay = 24 * 3600 * 1000;

for (var i = 0; i < 500; i++){

? var now = new Date(base += oneDay);

? date.push([now.getFullYear(), now.getMonth() + 1, now.getDate()].join('/'));

}

UTC時間和GMT(本地)時間之間的轉換:

GMT轉為UTC:

var now = new Date();

var nowUTC = new Date(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate(),

? ? ? ? ? ? ? ? ? ? ? now.getUTCHours(), now.getUTCMinutes(), now.getUTCSeconds());

UTC轉為GMT:

var nowGMT = Date.UTC(nowUTC.getFullYear(), nowUTC.getMonth(), nowUTC.getDate(),

? ? ? ? ? ? ? ? ? ? ? nowUTC.getHours(), nowUTC.getMinutes(), nowUTC.getSeconds());

var now = new Date(nowGMT)

注:?以北京時間為準,UTC總是比GMT小8個小時

常用API***************************************************************************************

Math.atan(n) ? ? ? ? ? ? ? //返回'反正切函數'arctan(n)的值,單位弧度,可轉換為角度

? 例: (Math.atan(a/b))*180/Math.PI

Math.abs(x) ? ? ? ? ? ? ? ?//返回數字的絕對值

? 例: Math.abs(a) || 1;

Math.min(x,y) ? ? ? ? ? ? ?//返回指定的數字中帶有最低值的數字

stringObject.substr(start,length) ?? //從字符串中抽取從start下標開始的指定數目(length)的字符

+str+1 ? ? ? ? ?//+可使字符串變為數字類型再計算

x=Number(x); ? ?//手動將字符串類型的數字轉換成Number類型,不直接修改原變量的值,而是返回新值

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容