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类型,不直接修改原变量的值,而是返回新值

推荐阅读更多精彩内容

  • 第2章 基本语法 2.1 概述 基本句法和变量 语句 JavaScript程序的执行单位为行(line),也就是一...
    枫叶appiosg阅读 2,956评论 0 13
  • --- 学习目标: - 掌握编程的基本思维 - 掌握编程的基本语法 typora-copy-images-to: ...
    YFBigHeart阅读 522评论 0 2
  • 君姐又搬家了。之所以是“又”,是因为这一次只是君姐二十余次搬家中的一次。回望君姐走过的这近二十年的教育生涯,用“惊...
    燕语诗心阅读 228评论 1 1
  • “生得好,不如嫁得好。”这句话,不知道从什么时候开始一直在我耳边环绕。 毕业前,我忙着找工作投简历,我身边的朋友已...
    姬樱阅读 1,385评论 6 1
  • 梦见一只会变成人形的狗,与小女主人相爱了
    刘省醒阅读 40评论 0 0