前端笔记

前端学习笔记十五-正则表达式及ES6

2019-10-28  本文已影响0人  AizawaSayo

一、正则表达式概述

1.1 什么是正则表达式

正则表达式( Regular Expression )是用于匹配字符串中字符组合的模式。在JavaScript中,正则表达式也是对象

正则表通常被用来检索、替换那些符合某个模式(规则)的文本,例如验证表单:用户名表单只能输入英文字母、数字或者下划线, 昵称输入框中可以输入中文(匹配)。此外,正则表达式还常用于过滤掉页面内容中的一些敏感词(替换),或从字符串中获取我们想要的特定部分(提取)等 。

其他语言也会使用正则表达式,本阶段我们主要是利用JavaScript 正则表达式完成表单验证。

1.2 正则表达式的特点

  1. 灵活性、逻辑性和功能性非常的强。
  2. 可以迅速地用极简单的方式达到字符串的复杂控制。
  3. 对于刚接触的人来说,比较晦涩难懂。比如:^\w+([-+.]\w+)@\w+([-.]\w+).\w+([-.]\w+)*$
  4. 实际开发,一般都是直接复制写好的正则表达式. 但是要求会使用正则表达式并且根据实际情况修改正则表达式. 比如用户名: /^[a-z0-9_-]{3,16}$/

二、正则表达式在js中的使用

2.1 正则表达式的创建

在 JavaScript 中,可以通过两种方式创建一个正则表达式。

方式一:通过调用RegExp对象的构造函数创建

var regexp = new RegExp(/123/);
console.log(regexp);

方式二:利用字面量创建 正则表达式

 var rg = /123/;

2.2 测试正则表达式

test() 正则对象方法,用于检测字符串是否符合该规则,该对象会返回 true 或 false,其参数是测试字符串。

var rg = /123/;
console.log(rg.test(123));//匹配字符中是否出现123  出现结果为true
console.log(rg.test('abc'));//匹配字符中是否出现123 未出现结果为false

三、正则表达式中的特殊字符

3.1 正则表达式的组成

一个正则表达式可以由简单的字符构成,比如 /abc/,也可以是简单和特殊字符的组合,比如 /ab*c/ 。其中特殊字符也被称为元字符,在正则表达式中是具有特殊意义的专用符号,如 ^ 、$ 、+ 等。

特殊字符非常多,可以参考:

MDN

jQuery 手册:正则表达式部分

[正则测试工具]( <http://tool.oschina.net/regex)

3.2 边界符

正则表达式中的边界符(位置符)用来提示字符所处的位置,主要有两个字符

边界符 说明
^ 表示匹配行首的文本(以谁开始)
$ 表示匹配行尾的文本(以谁结束)

如果 ^和 $ 在一起,表示必须是精确匹配

var rg = /abc/; // 正则表达式里面不需要加引号 不管是数字型还是字符串型
// /abc/ 只要包含有abc这个字符串返回的都是true
console.log(rg.test('abc'));
console.log(rg.test('abcd'));
console.log(rg.test('aabcd'));
console.log('---------------------------');
var reg = /^abc/;
console.log(reg.test('abc')); // true
console.log(reg.test('abcd')); // true
console.log(reg.test('aabcd')); // false
console.log('---------------------------');
var reg1 = /^abc$/; // 精确匹配 要求必须是 abc字符串才符合规范
console.log(reg1.test('abc')); // true
console.log(reg1.test('abcd')); // false
console.log(reg1.test('aabcd')); // false
console.log(reg1.test('abcabc')); // false

3.3 字符类

字符类表示有一系列字符可供选择,只要匹配其中一个就可以了。所有可供选择的字符都放在方括号内。

3.3.1 [] 方括号

表示有一系列字符可供选择,只要匹配其中一个就可以了
[a-z]中的-是字符范围符,表示匹配的这个字符(字母|数字|汉字)的可选范围
[^abc]内的^是取反符,表示取a、b、c三个字符以外的一个符号才会true

var rg = /[abc]/; // 只要包含有a 或者 包含有b 或者包含有c 都返回为true
console.log(rg.test('andy'));//true
console.log(rg.test('baby'));//true
console.log(rg.test('color'));//true
console.log(rg.test('red'));//false
var rg1 = /^[abc]$/; // 三选一 只有是a 或者是 b  或者是c 这三个字母才返回 true
console.log(rg1.test('aa'));//false
console.log(rg1.test('a'));//true
console.log(rg1.test('b'));//true
console.log(rg1.test('c'));//true
console.log(rg1.test('abc'));//false
----------------------------------------------------------------------------------
var reg = /^[a-z]$/ //26个英文字母任何一个字母返回 true  - 表示的是a到z的范围  
console.log(reg.test('a'));//true
console.log(reg.test('z'));//true
console.log(reg.test('A'));//false
console.log(reg.test('ah'));//false
-----------------------------------------------------------------------------------
//字符组合
var reg1 = /^[a-zA-Z0-9_-]$/; // 26个英文字母(大写和小写都可以)或下划线或短横线,任何一个字符返回 true  
console.log(reg1.test('D'));//true
console.log(reg1.test('5'));//true
console.log(reg1.test('-'));//true
console.log(reg1.test('_'));//true
console.log(reg1.test('!'));//false
------------------------------------------------------------------------------------
//取反 方括号内部加上 ^ 表示取反,只要包含方括号内的字符,都返回 false 。
var reg2 = /^[^a-zA-Z0-9]$/;
console.log(reg2.test('a'));//false
console.log(reg2.test('B'));//false
console.log(reg2.test(8));//false
console.log(reg2.test('!'));//true
console.log(reg2.test('!@'));//false
3.3.2 量词符

量词符用来设定某个模式出现的次数。

量词 说明
* 重复0次或更多次
+ 重复1次或更多次
? 重复0次或1次
{n} 重复n次
{n,} 重复n次或更多次
{n,m} 重复n到m次
 // 1. * 相当于 >= 0 可以出现0次或者很多次 
 var reg = /^a*$/;
 console.log(reg.test(''));//true
 console.log(reg.test('a'));//true
 console.log(reg.test('aa'));//true
 console.log(reg.test('aaaaaa'));//true
 // 2. + 相当于 >= 1 可以出现1次或者很多次
 var reg1 = /^a+$/;
 console.log(reg1.test(''));//false
 console.log(reg1.test('a'));//true
 console.log(reg1.test('aa'));//true
 console.log(reg1.test('aaaaaa'));//true
 // 3. ?  相当于 1 || 0
 var reg2 = /^a?$/;
 console.log(reg2.test(''));//true
 console.log(reg2.test('a'));//true
 console.log(reg2.test('aa'));//false
 console.log(reg2.test('aaaaaa'));//false
 // 4. {3 } 就是重复3次
 var reg3 = /^a{3}$/;
 console.log(reg3.test(''));//false
 console.log(reg3.test('a'));//false
 console.log(reg3.test('aa'));//false
 console.log(reg3.test('aaaaaa'));//false
 console.log(reg3.test('aaa'));//true
 // 5. {3, }  大于等于3
 var reg4 = /^a{3,}$/;
 console.log(reg4.test(''));//false
 console.log(reg4.test('a'));//false
 console.log(reg4.test('aa'));//false
 console.log(reg4.test('aaaaaa'));//true
 console.log(reg4.test('aaa'));//true
 // 6. {3, 16}  大于等于3 并且 小于等于16
 var reg5 = /^a{3,16}$/;
 console.log(reg5.test(''));//false
 console.log(reg5.test('a'));//false
 console.log(reg5.test('aa'));//false
 console.log(reg5.test('aaaaaa'));//true
 console.log(reg5.test('aaa'));//true
 console.log(reg5.test('aaaaaaaaaaaaaaaaaaaaa'));//false
3.3.3 用户名表单验证

功能需求:

  1. 如果用户名输入合法, 则后面提示信息为: 用户名合法,并且颜色为绿色
  2. 如果用户名输入不合法, 则后面提示信息为: 用户名不符合规范, 并且颜色为红色

分析:

  1. 用户名只能为英文字母,数字,下划线或者短横线组成, 并且用户名长度为6~16位.
  2. 首先准备好这种正则表达式模式/$[a-zA-Z0-9-_]{6,16}^/
  3. 当表单失去焦点就开始验证.
  4. 如果符合正则规范, 则让后面的span标签添加 right类.
  5. 如果不符合正则规范, 则让后面的span标签添加 wrong类.
<input type="text" class="uname"> <span>请输入用户名</span>
 <script>
 //  量词是设定某个模式出现的次数
 var reg = /^[a-zA-Z0-9_-]{6,16}$/; // 这个模式用户只能输入英文字母 数字 下划线 中划线
 var uname = document.querySelector('.uname');
 var span = document.querySelector('span');
 uname.onblur = function() {
   if (reg.test(this.value)) {
   console.log('正确的');
   span.className = 'right';
   span.innerHTML = '用户名格式输入正确';
   } else {
   console.log('错误的');
   span.className = 'wrong';
   span.innerHTML = '用户名格式输入不正确';
   }
 }
</script>
3.3.4 括号总结
  1. 大括号 量词符。里面表示它前面那个字符重复次数(不是所有整段文本)
var reg1 = /^abc{3}$/; // 它只是让c重复三次   abccc
console.log(reg1.test('abc'));//false
console.log(reg1.test('abcabcabc'));//false
console.log(reg1.test('abccc'));//true
  1. 中括号 字符集合。匹配方括号中的任意字符.
var reg = /^[abc]$/;
//精确匹配a b c其中一个字符就可以。a || b || c
  1. 小括号表示优先级
var reg2 = /^(abc){3}$/; // 它是让abcc重复三次
console.log(reg2.test('abc'));//false
console.log(reg2.test('abcabcabc'));//true

正则表达式在线测试

3.4 预定义类

预定义类指的是某些常见模式的简写方式.

案例:验证座机号码
正则表达式中的或:

var reg = /^\d{3}-\d{8}|\d{4}-\d{7}$/;
//以下方式更简洁
var reg = /^\d{3,4}-\d{7,8}$/;

表单验证案例

//手机号验证:/^1[3|4|5|7|8][0-9]{9}$/;
//验证通过与不通过更换元素的类名与元素中的内容
 if (reg.test(this.value)) {
    // console.log('正确的');
    this.nextElementSibling.className = 'success';
    this.nextElementSibling.innerHTML = '<i class="success_icon"></i> 恭喜您输入正确';
   } else {
       // console.log('不正确');
      this.nextElementSibling.className = 'error';
      this.nextElementSibling.innerHTML = '<i class="error_icon"></i>格式不正确,请从新输入 ';
 }
//QQ号验证: /^[1-9]\d{4,}$/; 
//昵称验证:/^[\u4e00-\u9fa5]{2,8}$/
//验证通过与不通过更换元素的类名与元素中的内容 ,将上一步的匹配代码进行封装,多次调用即可
 function regexp(ele, reg) {
    ele.onblur = function() {
      if (reg.test(this.value)) {
        // console.log('正确的');
        this.nextElementSibling.className = 'success';
        this.nextElementSibling.innerHTML = '<i class="success_icon"></i> 恭喜您输入正确';
   } else {
     // console.log('不正确');
     this.nextElementSibling.className = 'error';
     this.nextElementSibling.innerHTML = '<i class="error_icon"></i> 格式不正确,请从新输入 ';
            }
        }
 };
//密码验证:/^[a-zA-Z0-9_-]{6,16}$/
//再次输入密码只需匹配与上次输入的密码值 是否一致

3.5 正则替换replace

replace() 方法可以实现替换字符串操作,用来替换的参数可以是一个字符串或是一个正则表达式。
/表达式/[switch]
switch(也称为修饰符)参数为按照什么样的模式来匹配

var str = 'andy和red';
var newStr = str.replace('andy', 'baby');
console.log(newStr)//baby和red
//等同于 此处的andy可以写在正则表达式内
var newStr2 = str.replace(/andy/, 'baby');
console.log(newStr2)//baby和red
//全部替换
var str = 'abcabc'
var nStr = str.replace(/a/,'哈哈')
console.log(nStr) //哈哈bcabc
//全部替换g
var nStr = str.replace(/a/a,'哈哈')
console.log(nStr) //哈哈bc哈哈bc
//忽略大小写i
var str = 'aAbcAba';
var newStr = str.replace(/a/gi,'哈哈')//"哈哈哈哈bc哈哈b哈哈"

案例:过滤敏感词汇

<textarea name="" id="message"></textarea> <button>提交</button>
<div></div>
<script>
    var text = document.querySelector('textarea');
    var btn = document.querySelector('button');
    var div = document.querySelector('div');
    btn.onclick = function() {
        div.innerHTML = text.value.replace(/激情|gay/g, '**');
    }
</script>

3.6 字符串提取

字符串.match(正则表达式)可以对字符串进行提取操作,返回值是一个数组

var str = '小明:大神么么哒,正好是我想要的,我的邮箱是xiaoming@qq.com小红:我老公最爱看这个了,我想给他一个惊喜,么么么哒,邮箱是xiaohong@sina.com我:好人一生平安,邮箱是wuyou@163.com';
// 提取字符串str中的邮箱内容,注意,需要在正则的最后添加匹配模式g,不要设置严格匹配。
var str1 = str.match(/\w+@\w+\.\w+/g)
console.log(str1);

四、ES6相关概念(★★)

4.1 什么是ES6

ES 的全称是 ECMAScript , 它是由 ECMA 国际标准化组织,制定的一项脚本语言的标准化规范。

ES6泛指2015年6月及以后的版本

4.2 为什么使用 ES6 ?

每一次标准的诞生都意味着语言的完善,功能的加强。JavaScript语言本身也有一些令人不满意的地方。

五、ES6新增语法

5.1 let(★★★)

ES6中新增了用于声明变量的关键字

let声明的变量只在所处于的块级有效

可以防止内层变量覆盖外层变量。

 if (true) { 
     let a = 10;
     var b = 20;
     console.log(a);
 }
console.log(b);//20
console.log(a) // a is not defined

块级 :if{} for循环
注意:使用let关键字声明的变量才具有块级作用域,使用var声明的变量不具备块级作用域特性。

不存在变量提升
console.log(a); // a is not defined 
let a = 20;
暂时性死区

利用let声明的变量会绑定在这个块级作用域,不会受外界的影响,不会再去外部作用域查找是否有同名变量

 var tmp = 123;
 if (true) { 
     tmp = 'abc';//Cannot access 'num' before initialization
     console.log(tmp);
     let tmp; 
 } 
经典面试题
 var arr = [];
 for (var i = 0; i < 2; i++) {
     arr[i] = function () {
         console.log(i); 
     }
 }
 arr[0]();
 arr[1]();

经典面试题图解:此题的关键点在于变量i是全局的,函数执行时输出的都是全局作用域下的i值。

 let arr = [];
 for (let i = 0; i < 2; i++) {
     arr[i] = function () {
         console.log(i); 
     }
 }
 arr[0]();
 arr[1]();

经典面试题图解:此题的关键点在于每次循环都会产生一个块级作用域,每个块级作用域中的变量都是不同的,函数执行时因为它本身作用域下没有i变量,根据作用域链去查找后,输出的是自己上一级(循环产生的块级作用域)作用域下的i值

小结

5.2 const(★★★)

声明常量,常量就是值(内存地址)不能变化的量

具有块级作用域
 if (true) { 
     const a = 10;
 }
console.log(a) // a is not defined
声明常量时必须赋值
const PI; // Missing initializer in const declaration
常量赋值后,值不能修改。如果值是一个内存地址(存了数组或者对象),那么可以对它里面的元素进行修改,但不能重新赋值(比如直接赋值一个新数组|新对象|简单数据类型)
const PI = 3.14;
PI = 100; // Assignment to constant variable.

const ary = [100, 200];
ary[0] = 'a';
ary[1] = 'b';
console.log(ary); // ['a', 'b']; 
ary = ['a', 'b']; // Assignment to constant variable.
小结

5.3 let、const、var 的区别

5.4 解构赋值(★★★)

ES6中允许从数组中提取值,按照对应位置,对变量赋值,对象也可以实现解构

5.4.1 数组解构

变量接收到一一对应的每一个值,如果数组长度少于[]内变量个数,则多出来的变量得到的是undefined

 let [a, b, c,d] = [1, 2, 3];
 console.log(a)//1
 console.log(b)//2
 console.log(c)//3
 console.log(d)//如果解构不成功,变量的值为undefined
5.4.2 对象解构

方法一:变量匹配的是每一个元素的属性,接收到的值是每一个元素的值。

 let person = { name: 'zhangsan', age: 20 }; 
 let { name, age } = person;
 console.log(name); // 'zhangsan' 
 console.log(age); // 20

方法二:左边也以对象的形式,里面的【值】变量接收的是对应元素属性的值。

 let {name: myName, age: myAge} = person; // myName myAge 属于别名
 console.log(myName); // 'zhangsan' 
 console.log(myAge); // 20

小结

5.5 箭头函数(★★★)

ES6中新增的定义函数的方式。

() => {} //():代表是函数; =>:必须要的符号,指向哪一个代码块;{}:函数体
const fn = () => {}//代表把一个函数赋值给fn

函数体中只有一句代码,且代码的执行结果就是返回值,可以省略大括号

 function sum(num1, num2) { 
     return num1 + num2; 
 }
 //es6写法
 const sum = (num1, num2) => num1 + num2; 

如果形参只有一个,可以省略小括号

 function fn (v) {
     return v;
 } 
//es6写法
 const fn = v => v;

箭头函数不绑定this关键字(没有属于自己的this),箭头函数中的this,指向的是函数定义位置的上下文this。如下,箭头函数被定义在fn内,它的this就跟随fn的this变成了obj

const obj = { name: '张三'} 
 function fn () { 
     console.log(this);//this 指向 是obj对象
     return () => { 
         console.log(this);//this 指向 的是箭头函数定义的位置,那么这个箭头函数定义在fn里面,而这个fn指向是的obj对象,所以这个this也指向是obj对象
     } 
 } 
 const resFn = fn.call(obj); 
 resFn();
小结
面试题

关键点:对象没有作用域,say方法是被定义在全局作用域下的

var age = 100;

var obj = {
    age: 20,
    say: () => {
        alert(this.age)
    }
}

obj.say();//100 箭头函数this指向的是被声明的作用域里面,而对象没有作用域的,所以箭头函数虽然在对象中被定义,但是this指向的是全局作用域

5.6 剩余参数(★★)

剩余参数语法允许我们将一个不定数量的参数表示为一个数组,不定参数定义方式,这种方式很方便的去声明不知道参数情况下的一个函数

function sum (first, ...args) {
     console.log(first); // 10
     console.log(args); // [20, 30] 
 }
 sum(10, 20, 30)
 var sum = (...args) => {
     let total = 0;
     args.forEach(item=>total+= item)
     return total;
 }
 sum(1,2,3)
 sum(5,6) 
剩余参数和解构配合使用
let students = ['wangwu', 'zhangsan', 'lisi'];
let [s1, ...s2] = students; 
console.log(s1);  // 'wangwu' 
console.log(s2);  // ['zhangsan', 'lisi']

六、ES6 的内置对象扩展

6.1 Array 的扩展方法(★★)

扩展运算符(展开语法)

扩展运算符可以将数组或者对象转为用逗号分隔的参数序列
如下例子,逗号都当作参数中间的分隔符

 let ary = [1, 2, 3];
 ...ary  // 1, 2, 3
 console.log(...ary);    // 1 2 3,相当于下面的代码
 console.log(ary[0], ary[1], ary[2]);
扩展运算符可以应用于合并数组
// 方法一 
 let ary1 = [1, 2, 3];
 let ary2 = [3, 4, 5];
 let ary3 = [...ary1, ...ary2];
 // 方法二 
 ary1.push(...ary2);
将类数组或可遍历对象转换为真正的数组
let oDivs = document.getElementsByTagName('div'); 
oDivs = [...oDivs];
构造函数方法:Array.from()

将伪数组或可遍历对象转换为真正的数组

//定义一个集合
let arrayLike = {
    '0': 'a',
    '1': 'b',
    '2': 'c',
    length: 3
}; 
//转成数组
let arr2 = Array.from(arrayLike); // ['a', 'b', 'c']

方法还可以接受第二个参数,作用类似于数组的map方法,用来对每个元素进行处理,将处理后的值放入返回的数组

 let arrayLike = { 
     "0": 1,
     "1": 2,
     "length": 2
 }
 let newAry = Array.from(arrayLike, item => item *2)//[2,4]

注意:如果是对象,那么属性需要写对应的索引

实例方法:find()

用于找出第一个符合条件的数组成员,如果没有找到返回undefined

let ary = [{
     id: 1,
     name: '张三'
 }, { 
     id: 2,
     name: '李四'
 }]; 
 let target = ary.find((item, index) => item.id == 2);//找数组里面符合条件的值,当数组中元素id等于2的查找出来,注意,只会匹配第一个
console.loe(target);//Object{id:2,name:'李四'}
实例方法:findIndex()

用于找出第一个符合条件的数组成员的位置(在数组中的索引),如果没有找到返回-1

let ary = [1, 5, 10, 15];
let index = ary.findIndex((value, index) => value > 9); 
console.log(index); // 2
实例方法:includes()

判断某个数组是否包含给定的值,返回布尔值。

[1, 2, 3].includes(2) // true 
[1, 2, 3].includes(4) // false

6.2 String 的扩展方法

模板字符串(★★★)

ES6新增的创建字符串的方式,使用反引号定义

let name = `zhangsan`;
模板字符串中可以解析变量
let name = '张三'; 
let sayHello = `hello,my name is ${name}`; // hello, my name is zhangsan
模板字符串中可以换行
 let result = { 
     name: 'zhangsan', 
     age: 20,
     sex: '男' 
 } 
 let html = ` <div>
     <span>${result.name}</span>
     <span>${result.age}</span>
     <span>${result.sex}</span>
 </div> `;

在模板字符串中可以调用函数
const sayHello = function () { 
    return '哈哈哈哈 追不到我吧 我就是这么强大';
 }; 
 let greet = `${sayHello()} 哈哈哈哈`;
 console.log(greet); // 哈哈哈哈 追不到我吧 我就是这么强大 哈哈哈哈
实例方法:startsWith() 和 endsWith()
let str = 'Hello world!';
str.startsWith('Hello') // true 
str.endsWith('!')       // true
实例方法:repeat()

repeat方法表示将原字符串重复n次,返回一个新字符串

'x'.repeat(3)      // "xxx" 
'hello'.repeat(2)  // "hellohello"

6.3 Set 数据结构(★★)

ES6 提供了新的数据结构 Set。它类似于数组,但是成员的值都是唯一的,没有重复的值。因此可以用它来做数组去重

Set本身是一个构造函数,用来生成 Set 数据结构

const s = new Set();

Set函数可以接受一个数组作为参数,用来初始化。size是它的长度属性

const set = new Set([1, 2, 3, 4, 4]);//{1, 2, 3, 4}
console.log(set.size) //4 
const arr = [...set]//利用扩展运算符转化为数组
console.log(arr)
实例方法
 const s = new Set();
 s.add(1).add(2).add(3); // 向 set 结构中添加值,可以链式调用 
 s.delete(2)             // 删除 set 结构中的2值   返回布尔值
 s.has(1)                // 表示 set 结构中是否有1这个值 返回布尔值 
 s.clear()               // 清除 set 结构中的所有值
 //注意:删除的是元素的值,不是代表的索引
遍历

Set 结构的实例与数组一样,也拥有forEach方法,用于对每个成员执行某种操作,没有返回值。

s.forEach(value => console.log(value))
上一篇下一篇

猜你喜欢

热点阅读