正则表达式&函数
页面加载顺序:html -> css -> js
如果js部分写在页面内容前面,加载顺序:js -> html,js部分无法找到执行对象,获取的html元素就出现undefined的错误;
1)加window.function(){}
2)js内容放在页面内容之后,%lt;/script>标签要紧挨着</body>标签
1 正则表达式RegExp
1.1 概述
Regular Expression:由普通字符和特殊字符组成以描述特定字符规则的表达式;常用于在文本中搜索,匹配,替换特定形式的文本
1.2 定义
除开所有大小写字母和数字,部分字符有特殊语法含义,必须使用\进行转义:. \ / * ? + [ ( ) ] { } ^ $ |
-
字符集:正则表达式匹配范围内的字符
语法 含义 [abc] 匹配指定集合内的任一个字符 [^abc] 匹配不在集合内的任意字符 [0-9] 一个数字 [a-z] 一个小写字母 [A-Z] 一个大写字母 [A-Za-z] 一个字母 [A-Za-z0-9] 一位数字或字母 [\u4e00-\u9fa5] 一个汉字 -
预定义字符集:对常用字符集简化写法
语法 含义 \d 匹配一个数字 \D 匹配非数字 \w 匹配数字/字母/下划线 \W 匹配非数字/字母/下划线 \s 匹配空字符 \S 匹配非空字符 . 除回车换行的任何字符 -
量词:规定字符出现次数
重复字符 含义 {x} 必须x位 {x,y} x到y位 {x,} x位以上 * 可有可无,数量不限 ? 可有可无,最多一个 + 可有可无,至少一个 -
选择分组
使用()指定分组,使用|进行条件选择;
|只匹配左右所有字符,不会考虑单个字符 -
匹配位置
重复字符 含义 ^ 字符串开头 $ 字符串结尾 b 单词边界 B 单词非边界 ?=x 之后紧接x的字符串 ?!x 之后没有紧接x的字符串
1.3 RegExp对象
专门保存正则表达式的对象,提供正则表达式执行验证和查找的API.
- 直接量创建:var reg=/正则/ig;
- 用程序动态生成:var reg=new RegExp(“正则表达式”,“ig”)参数列表中式字符串,所以可以能够js动态生成;
常用API:reg.test(str)检查字符串str的格式,只要部分规则符合就返回true;可以通过前加^后加$从头到尾完整匹配;
reg.exec(str)在str中查找下一个符合reg要求的关键词的内容和位置,使用循环反复调用直至返回null
1.4 模式匹配
1.4.1 查找关键词
- 查找一个固定的敏感词出现的位置:
回顾: str.indexOf()
var i=str.indexOf(“敏感词”,starti)
在str中,从starti位置开始,查找下一个“敏感词”的位置
省略第二个参数starti,默认从0位置开始查找
返回值: 如果找到,返回敏感词第一个字的位置
如果找不到,返回-1
问题: 只能查找一种固定的敏感词 - 模糊查找符合正则表达式要求的敏感词:
var i=str.search(/正则/);
在str中查找第一个符合正则要求的敏感词的位置
返回值: 如果找到,返回敏感词第一个字的位置
如果找不到,返回-1
问题1: 正则默认都是区分大小写的
解决: 在第二个/后加后缀i, ignore
问题2: 只能返回位置i,无法返回敏感词的内容 - 查询敏感词的内容: 2种情况:
- 只查看第一个敏感词的内容和位置:
var arr=str.match(/正则/i);
在str中查找第一个符合正则要求的敏感词的内容和位置
返回值: 如果找到: arr:[ 0:“敏感词”, index: 位置i ]
补充: js中其实一切都是关联数组
如果找不到: 返回null
强调: 如果一个函数有可能返回null,都要先验证不是null,再使用。
问题: 正则表达式默认只找到第一个就退出
解决: 在第二个/后加后缀g, global(全部) - 查找所有敏感词的内容:
var arr=str.match(/正则/ig)
在str中查找所有符合正则要求的敏感词的内容
返回值: 如果找到: arr: [ 敏感词1, 敏感词2,… ]
如果没找到,返回null
问题: 只能获得内容,无法获得位置
- 只查看第一个敏感词的内容和位置:
- 查找每个敏感词的内容和位置: reg.exec()
1.4.2 替换
- 简单替换: 将所有敏感词都替换为统一的新值:
str=str.replace(/正则/ig,“新值”)
查找str中符合正则要求的所有敏感词,替换为统一的新值
强调: 所有字符串API是无权直接修改原字符串,总是返回新字符串作为处理结果,所以必须用变量接住返回的新字符串。 - 高级替换: 可根据每次找到的敏感词不同,动态生成替换的新值
str=str.replace(/正则/ig,function(kword){
return 新值
});
查找str中每个符合正则要求的敏感词,每找到一个敏感词,就自动调用一次回调函数。每次调用时,都自动传入本次的敏感词作为参数kword,再将返回的新值,替换回字符串中。
衍生操作: 删除找到的敏感词,其实就是替换为""
1.4.3 切割
将一个字符串按指定的分隔符切割为多段子字符串:
- 简单切割: 切割符是固定的:
回顾: var arr=str.split(“切割符”) - 复杂切割: 切割符不是固定的
var arr=str.split(/正则/)
2 函数Function
2.1 Function对象
函数在JavaScript中以对象形式存在,函数名的本质是变量,指向Function对象的引用。有三种创建方式:
-
直接量声明
function 函数名(形参列表){ 函数体; return 返回值; }
问题: 会被声明提前
解决: 改声明方式为赋值方式 -
赋值
var 函数名=function (形参列表){ 函数体; return 返回值; }
优点: 因为是赋值方式,不会被声明提前
揭示了js中函数的本质:- 函数其实也是一个保存一段代码的对象;
- 函数名其实只是一个普通的变量而已。函数名变量通过函数对象的地址引用着函数对象。所以使用函数名变量等效于使用函数对象本身。
-
用new Function构造函数创建函数对象:
var 函数名=new Function(“形参1”,“形参2”,…,“函数体”)
效率远不如直接使用function关键字定义函数(字符串需要再次解析),但方法体是字符串,可以在运行时动态创建修改执行
垃圾回收:引擎会自动检测不再使用的对象,并自动释放内容空间,因为内存容量极其有限;垃圾回收器是专门检测并回收垃圾对象的小程序,伴随主程序执行而并行执行,当对象不再被任何变量引用就自动释放,不再使用的对象,要将其赋值为null
2.2 闭包
2.2.1 匿名函数
如果一个函数只使用一次,不会重用时,都要用匿名函数
非匿名函数在定义时就已创建函数对象和作用域链对象,所以未被调用也占用内存空间。
匿名函数:定义时未指定函数名的函数,仅在调用时临时创建函数对象和作用域链对象,并在调用完后立刻释放。
- 回调函数:自己定义给其它函数调用;
- 匿名函数自调:定义函数后立刻执行;几乎所有js代码都装在匿名函数自调中,避免使用全局变量造成全局污染;
(function(参数列表){ 函数体; return 返回值 })(参数值列表) 第一个圆括号相当于返回函数地址
匿名函数比非匿名函数更节省内存空间
2.2.2 作用域和作用域链
作用域scope:程序中定义变量的使用范围,避免函数内外的变量间相互干扰。可分为全局作用域和函数作用域,优先使用局部变量,函数对象使用scope属性指向自己所在的作用域。
作用域链scope chain:由多级作用域逐级引用形成的链式结构(专门保存函数可用变量存储位置的对象);每个函数对象都对应一个作用域链对象
2.2.3 闭包
闭包:重用变量,保护变量不被篡改的机制。全局变量可重用,但随处可用且易被篡改;局部变量不可重用。
闭包的三个步骤:
- 用外层函数包裹受保护的变量和内层函数;
- 外层函数将内层函数对象返回到外部:三种方式(1.return;2.给全局变量赋值;3.内层函数包裹在数组/对象中返回);
- 调用外层函数获得内层函数的对象;
形成原因:外层函数的函数作用域对象无法释放,所以内层函数比普通函数占用更多内存空间(外层函数的作用域AO);
寻找闭包:找受保护的变量(外层函数的局部变量);找外层函数返回的内层函数(一次外层函数调用返回的内层函数共用同一个闭包中受保护的变量)
不再使用闭包应立刻释放闭包结构
结合匿名函数调用闭包的外层函数:
var zan = (function(){
var n=0;
return function () {
n++;
document.write(`共${n}赞`);
}
})();