- RegExp对象
******Function****** - 回顾函数
- 创建函数三种方式
- 重载
- 匿名函数
- 作用域和作用域链
一. RegExp对象:
问题: 其实,js语言默认看不懂正则表达式的!就要一种东西,可以将正则表达式翻译为js可以看懂的内容,并执行验证和查找功能。
什么是RegExp对象: 专门在js中保存一条正则表达式,并提供验证和查找功能的特殊对象。
何时: 今后只要想在js中用正则表达式执行验证和查找功能,都要用RegExp对象
-
如何创建: 2种方式:
(1). 标准: var 变量=new RegExp("正则","ig");
a. 今后,只要正则表达式需要用程序动态生成时,都用new RegExp()来创建
b. 原理: new RegExp()中需要的是一个字符串类型的正则表达式。而在js语言中,有无数种方法,可以拼接出我们想要的任意字符串来!
c. 坑: 正则中有\d等写法,js的字符串中也有\t、\n写法。正则中的\和js字符串中的\冲突了!
d. 解决: 今后,只要在new RegExp()的""中出现\,都要改为\
比如: new RegExp("\d{6}") //6位数字
应该改为: new RegExp("\d{6}")
其中: 第一个\是js中的转义字符,意思是告诉js,后续的内容与js字符串无关!不要按js解析!
第二个\才是和\d组合的正则表达式字符集,表示一位数字。
js地盘 |正则| js地盘
(2). 简写: var 变量=/正则/ig;
a. 问题: //之中是正则表达式的地盘,其中不认识js变量或js表达式。
b. 所以,将来只有正则表达式是固定不变的时候,才会用//来创建正则表达式。如果正则表达式需要用程序动态生成时,是不能用//创建正则表达式的。
c. 比如: 手机、电子邮件、url网址...(1). 示例: 根据数组内容查找多种敏感词
1_new_RegExp.html
5. 验证字符串格式:
(1). var 验证结果=正则表达式对象.test(要验证的字符串)
(2). 意为: 用正则表达式验证要验证的字符串是否符合格式要求!
(3). 返回值: 如果字符串符合正则表达式要求,就返回true;否则,如果字符串不符合正则表达式要求,就返回false。
(4). 问题: 正则表达式默认,只要部分匹配就返回true。默认不要求从头到尾必须完整匹配.
(5). 解决: 今后,只要要求必须重头到尾完整匹配,就必须同时前加^,后加$。
(6). 示例: 验证用户输入的手机号格式是否正确:
6. 查找敏感词:
(1). 只查找一个敏感词的内容和位置:
a. var 数组=正则表达式对象.exec(字符串)
b. 意为: 在字符串中查找第一个符合正则表达式对象要求的敏感词的内容和位置。
c. 与search()的差别:
1). search(),只能获得敏感词的位置,无法获得敏感词的内容
2). exec(),既可获得敏感词内容,又可获得敏感词位置
d. 返回值:
1). 如果找到敏感词,就会返回一个数组:
i. 数组: [ 0: "敏感词的内容", index:敏感词的下标位置 ]
ii. 比如: 那天,我去了她家,我说:我草!你家真大
0 1 2 3 4 5 6 7 8 9 0 1 2
会返回数组: [ 0:"我草", index:12 ]
iii. 强调: exec()是浏览器已经定义好的函数。不是我们自己写的!所以,用别人写好的函数,首先要学会听话!别人说,让你去哪个位置访问,你就只能去那个位置访问!背过!没有为什么!
iv. 所以:
想获取本次找到的敏感词内容:
数组["0"],可简写为: 数组[0]
想获取本次找到的敏感词位置:
数组["index"],可简写为: 数组.index
2). 如果没找到敏感词,就返回null。
所以,可以用if(数组!=null)来判断本次是否找到了敏感词
e. 示例: 查找一个敏感词的内容和位置:
f. 问题: 只能查找一个敏感词,无法查找所有敏感词。
(2). 查找所有敏感词内容和位置
a. 2步:
1). 正则表达式要加后缀g,意为global,表示全部。
i. 依然无法找所有。
ii. 因为reg.exec()采用狗熊掰棒子的方式,查找敏感词的。
每次只能找一个敏感词,放入数组中。数组中也只能放一个敏感词的内容和位置.
再找下一个敏感词时,就会丢弃旧的敏感词,把数组中换成新的敏感词。结果,数组中始终只保存一个敏感词。
2). 必须配合循环反复调用!
var reg=/正则/g;
//无论字符串是否包含敏感词,都要先找一次,才能确定是否有必要继续找。
do{//所以,选择do while循环
var arr=reg.exec(字符串);
if(arr!=null){
对本次找到的数组arr内容执行操作
}
}while(arr!=null); //只有本次找到了敏感词,才有必要继续找下一次
b. 示例: 查找字符串中所有以小字开头的人名。
****Function****
一. 回顾函数:
问题: 在程序中有很多代码片段,可能被多次反复使用。如果重复编写很多遍,或复制粘贴很多遍,极其不便于维护。修改时,复制过多少次副本,就要重复修改多少处!只要有一处忘记修改,程序就会出错!
解决: 今后,只要会被反复使用的代码段,都要保存在函数中,并反复调用函数。
什么是函数: 内存中,一块专门存储代码片段的存储空间,再起一个名字。
-
如何: 2步:
(1). 定义函数,保存一段可重用的代码片段,再起一个名字:
function 函数名(){
要反复调用的代码片段
}
其中: function是new Function()的缩写!程序中,只要读到一个function,就会立刻在内存中,创建一个存储空间,用来存储一端代码片段。
问题: function,只负责创建新函数,保存代码片段,不负责执行函数!(2). 调动函数:
a. 函数名();
b. 意为: 让程序找到指定名称的函数,自动执行函数中的代码片段。
c. 问题: 函数内的变量都是写死的!一个函数无法处理多种不同数据的情况
5. 定义参数:
(1). 何时: 今后,只要一个函数内部有不确定来源的变量时(不是我自己var的),都要为函数定义参数。
(2). 如何: 2步:
a. 在创建函数时,定义形参变量:
function 函数名(形参变量1, 形参变量2, ...){
函数体中:
就可使用形参变量1和形参变量2暂时为将来可能的数据占位。
}
b. 将来调用函数时,给函数的形参变量传递实参值
函数名(实参值1, 实参值2,...)
(3). 问题: 无法对函数的执行结果,继续执行后续操作!
6. 返回值:
(1). 何时: 今后,只要函数的外部,需要获得函数的执行结果,继续执行后续操作时,都要为函数定义返回值。
(2). 如何: 2步:
a. 创建函数时:
function 函数名(形参列表){
函数体
return 执行结果
}
b. 调用函数时:
var 变量=函数名(实参值列表);
c. 结果: 程序先调用函数,函数内的return关键字,会将执行结果抛出/返回到主程序中,保存到=前的变量里。之后就可被反复使用了!
- 示例: 定义函数,对数组内容求和
6_function.html
- 函数执行的本质:
(1). 所有程序自己都是不会执行的!
(2). 所有创建函数,调用函数,传参,遍历数组,计算,赋值都是由js引擎程序帮我们完成!
二. 创建函数: 3种方式:
1. 用声明方式: 必须包含四样东西: function,函数名,(),{}
(1). function 函数名(形参列表){
函数体
return 返回值
}
(2). 问题: 会被声明提前
a. 什么是:
1). 在程序开始执行前——时机
2). js引擎会扫描程序中2样东西:
var声明的变量 和 function声明的函数
3). 将这两样东西提前到当前作用域的顶部集中创建。
4). 赋值会被留在原地
5). 当声明提前阶段结束后,才开始正式执行程序的所有代码!
b. 缺点: 声明提前打乱了程序正常的执行顺序!极容易造成歧义和错误——JS语言广受诟病的缺陷
c. 鄙视时: 只要碰到声明提前的题,都要先把程序改造成声明提前之后的样式!再开始读改造后程序!
2. 用赋值方式创建:
(1). var 函数名=function(形参列表){
函数体
}
(2). 结果和第一种声明方式创建出来的函数是完全一样的!
(3). 优点: 因为这个格式不符合声明提前的语法格式,所以不会被提前!
(4). 总结: 今后,创建函数时,强烈建议都用赋值方式。
(5). 示例: 判断声明提前的程序的输出结果:
_hoist.html
运行结果:
undefined
10
1
2
- 用new: (几乎不用)
(1). var 函数名=new Function("形参1","形参2",...,"函数体")
(2). 揭示了: js中函数本质上也是一个引用类型的对象
a. 程序中所有小写的function,运行时都会被自动翻译为new Function。都会自动创建一个新对象,保存函数的定义。每个函数对象都有自己唯一的地址值。
b. 函数也可以用作变量赋值和传参。
c. 两个长得完全一样的函数,做==比较,返回false!
因为两个引用类型的对象做==比较,比的是地址值。
三. 重载(overload):
问题: 实际开发中,经常遇到一件事,可能根据传入的参数不同,执行不同的逻辑。但是,如果为一件事,创建多个不同名称的函数,将来调用时,极其麻烦!
解决: 重载
-
什么是: 为一件事,定义多个相同函数名,不同参数列表的多个函数。在调用时,程序可以自动根据我传入的实参值不同,自动选择执行对应版本的函数!
优点: 即使一个任务有多种不同的逻辑,也不用其很多的函数名。只需要一个函数名即可!
问题: js中不允许多个同名函数同时存在。如果存在,只有最后一个同名函数才能留下在!覆盖之前所有同名函数!——所以,js中不能用类似于Java中的重载!
解决: js中要变通实现: 2步:
(1). 只定义一个函数,且不要定义任何形参变量!
(2). 在函数内,自动由arguments对象接住所有的实参值。
a. 什么是: arguments对象是:
1). 每个函数中都自带的——不用我们自己创建,就可直接使用
2). 专门自动接受所有传入函数的实参值的——内容
3). 类数组对象——格式/存储结构
i. 什么是: 长的像数组的对象:
ii. 和数组相比:
相同点: 1. 数字下标, 2. length, 3. for循环遍历
不同点: 类数组对象不是数组类型的对象,而是Object类型的对象,不能使用数组家提供的所有函数。
b. 示例: 使用重载实现一个函数根据传入参数不同执行不同的付款方式
9_overload.html
运行结果:
四. 匿名函数:
- 什么是: 定义函数时,不指定函数名的函数
- 为什么: 2个原因:
(1). 节约内存: 匿名函数没有变量引用着,用完就释放了!
(2). 避免不同功能之间的程序互相干扰: 因为匿名函数也是函数,只要是函数,就都是作用域。内部的数据就无法超出函数的范围影响外部。 - 何时: 两种场景:
(1). 今后,只要回调函数,尽量都要用匿名函数
(2). 今后,只要担心一个功能的数据和另一个功能的数据之间互相干扰,就都可以用匿名函数自调,将不同的功能分块包裹起来!
五. 作用域(scope)和作用域链
对应小程序视频: 小程序->在线->JSCORE->day01 6. 简单作用域
- 什么是作用域: 一个变量的使用范围。
- 为什么: 避免不同范围之间的变量互相干扰。
- 包括: 2级:
(1). 全局作用域:
a. 什么是: 在程序的任何位置都可以访问到的范围
b. 其实:
1). 全局作用域也是一个对象: window
2). 其实我们在全局范围内创建的所有变量和函数,默认都是保存在window中。
(2). 函数作用域:
a. 什么是: 只能在函数内访问的范围
b. 函数作用域中创建的变量或函数,出了函数的范围都不能使用!
c. 在使用变量时:
1). 优先使用函数作用域内的局部变量
2). 局部没有,才被迫去全局范围内查找。 - 示例: 简单作用域练习:
11_scope.html