第五章*****************************************************************************************
什么是索引数组: 下标都是数字的数组
关联数组:
什么是: 可自定义下标名称的数组
为什么: 为了让每个元素都有一个专门的名称
好处: 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="
或 var html="
- "+uls.join("")+"
② 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 ③复制关联数组: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
否则返回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 for(var c=0;c
data[r][c] //获得当前元素 } } 创建二维数组: var arr=[]; for (var i=0;i arr[i]=[]; //创建一个二维数组,内容为空 for (var j=0;j arr[i][j]=0; } } 冒泡排序算法(一维数组): function bubblesort(arr){ for(varr=1;r for(vari=0;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 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 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 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类型,不直接修改原变量的值,而是返回新值