前端学习周记(1)——EC6&JS

慧慧结束了,长达几个月的划水生活,开始学一些东西了(希望期末这个不要挂)

这个是学长给的http://huziketang.mangojuice.top/books/react/(然后……真的是懵,框架是什么)


这篇文章主要会介绍ECMAScript 2015的基本语法(我学东西比较慢,然后最近还一堆课和考试,但是这个绝对不会坑的)

好了,先解决我的一些问题:

什么是ECMAScript 2015?

es6 是js语言的下一代标准,15年6月发布,也就是ECMAScript(2015)

-------------------历史引用自--------------

http://www.css88.com/archives/6200

首先回顾一下JavaScript的历史,不清楚历史的人,很难理解JavaScript为什么会这样发展。下面就是一个简单的JavaScript发展时间轴:

1、1995:JavaScript诞生,它的初始名叫LiveScript。

2、1997:ECMAScript标准确立。

3、1999:ES3出现,与此同时IE5风靡一时。

4、2000–2005: XMLHttpRequest又名AJAX, 在Outlook Web Access (2000)、Oddpost (2002),Gmail (2004)和Google Maps (2005)大受重用。

5、2009: ES5出现,(就是我们大多数人现在使用的)例如foreach,Object.keys,Object.create和JSON标准。

6、2015:ES6/ECMAScript2015出现。

----------------------------------------------------



下面进入正题

本文主要依据为书(如下图)以及各种各样的网站

大家也可以自行参观电子书,网址如下:

http://es6.ruanyifeng.com/#README


Ⅰ、let 和 const 命令

那么,var又是什么呢?

简而言之,就是声明一个变量。

在js中不声明而直接给一个变量赋值也是可以的,但这样的变量默认是全局的

#感觉这就像C++里在main函数外面声明函数和在main函数里面声明一样,然后也神似Python里的global关键字。



console.log()是什么用处呢?

http://www.ok12.net/js/about-js-console-log.html

console.log()在控制台中打印,打印任意字符或者js的变量信息;console.log()可以接受任何字符串、变量、数字、对象;

简而言之——就是为了好看


函数相关http://www.runoob.com/js/js-function-definition.html

和C++以及Python看起来差距不大,格式也比较类似都是一个函数的声明,参数,返回值。不再赘述。

下面还有些内容,不过等到需要用的时候吧




总之,和其他的const没什么区别。

当然还有其他声明变量的方法,比如global……




Ⅱ、变量的解构赋值

感到了一丝熟悉,好像列表哇。
-----------------------------------------------------------2018/5/9 21:09----------------------------------------------

不晓得为啥之前插入的图片只剩下来一张了,不过这都不重要,这些内容都可以在电子书中看到,再者一点一点写着实需要好久,再加上之前的编辑两次被删,已经失去耐心(寒假写Python读书笔记的时候,一篇耗时整整一早上,最近课和考试特别多,实在没有精力)然后,还看到了正则,记得Python就卡在正则表达式,希望可以借此机会弄明白
又及:刚刚CSDN的新编辑器很迷……我编辑的东西被自动删除了(好像是热键的问题,想在这里反馈一下:之前老版是不能总按退格键,不然会自动返回上一个界面,可以说是很不方便,但是好歹老版会自动保存一部分修改内容,但是这个新版,好像是不能连续按回车键,这就更不方便了,如果写的密密麻麻看起来会眼睛疼的,所以经常手动分段,这样很影响使用,而且还不保存修改,可以说是用户体验很不好了)

------------------------------------------------------------
分割线内内容CV自博客

地址如下:
https://www.cnblogs.com/Ari1c/p/8068176.html

侵删。

一.什么是es6

es6 是js语言的下一代标准,15年6月发布,也就是ECMAScript(2015)

ECMAScript就是JavaScript的国际标准,js是es的实现


es的历史:

1996年11月,网景公司把js语言提交给国际标准组织ECMA,希望能成为国际标准推广,1997年,ECMA发布ECMAScript 1.0

兼容的不是很好,但是写起来方便也多了很多新的好玩的东西

编译的话咱们就暂时先用咱们react使引入的哪个browser.js + type=‘text/bable’

不用的话也可能能用,但是有的地方就体现不出来了,还是编译的好

为什么要有es6呢?自己想一下去吧..

编译es6的方式:

1.浏览器编译

2.gulp


二.let 和 const命令

1.let:声明变量,声明的是局部变量

用途及区别:ES6新增了let命令,用来声明变量,类似于var ,但是声明的变量只在let所在的代码块的内部有效

let不存在变量提升,这个要注意哟

  • 暂时性的死区:

只要块级作用域里存在let命令,它所声明的变量就绑定这个区域,不在受外部的影响

  • 不允许重复声明

内部的数据有了let声明过之后不允许重复声明


2.块级作用域

为什么需要块级作用域:

es5只有全局作用域和函数作用域,这样会造成一些不合理的地方

1>.内部数据覆盖外部数据的情况

2>.用来计数的循环变量泄露成全局变量

虽然没有专业的定义词语来创建块级作用域,但是只要内部用了let,就说明一个块级作用域存在了,也就是说let命令为es6增加了块级作用域

在以往我们为了让变量执行完成后就销毁不要浪费内存,会把大段的代码放到立即执行函数里,而现在,我们只需要一个块级作用域就好了


3.const :

声明只读常量 一旦声明就不能进行更改,使用起来和var,let定义的的变量一样,也是属于块级的定义方式,和let相似,也是不可重复声明的

但是对象呀,数组呀都是可以改这个对象或者数组的东西的,因为真正保存的是地址,数组多个元素少个元素又不会改变地址

const person=Object.freeze({});
var cat=Object.freeze({});

赋值的时候可以用Object.freeze来冻结一个对象,使其内部的属性和方法不能更改


4.全局对象属性

全局对象是最顶层的对象,在浏览器环境指的是window对象,在node。js指的是global对象,在js语言里,所有变量都是全局对象的属性,

es6规定,var 和function声明的全局变量不属于全局对象的属性,let、const、class声明的全局变量不属于全局对象的属性


二.对象的解构赋值

destructuring es6允许按照一定模式,从数组和对象里提取值,对变量进行赋值,这被成为解构赋值

1.数组的解构赋值
var [a,b,c]=[1,2,3];

指定默认值 注意:es6内部使用严格相等运算符(===)判断一个位置上是否有值,所以如果一个数组成员不严格等于undefined,默认值是不会生效的

注意数组对应的如果不是数组的话就会报错

2.对象的解构赋值

解构不仅可以用于数组,还可以用于对象 对象的属性没有次序,变量必须与属性同名,才能取到正确的值

默认值生效的条件是,对象的属性值严格等于undefined

3.函数参数的解构赋值

在以前的时候,当用户传入数组或者对象的时候,需要在函数内部对这个数组或者对象进行解构并且赋值、设置默认值 es6可以直接在函数的形参部分进行解构赋值和设置默认值


三:模板字符串

1.es6提供了又一种变量连接字符串的方法:
var food='蛋糕';
             var drink='可乐'; var str=`今天的早餐是${food}和${drink}`;
2.es6觉得可以用一个函数来搞一搞这个字符串:

利用kitchen函数来操作拼接字符串的过程,注意的是这个函数的返回值就是最终的字符串 它接受两个参数,第一个是一个数组,前几位元素都是没有拼接变量时的每一个小的部分,并且这个数组有个属性叫raw,里面也会存放所有的元素 第二个参数可以用...的方式来接受所有的要拼接的变量

```
         let food='蛋糕';
         let drink='可乐';

         let str=kitchen`今天的早餐是${food}和${drink}`;
         function kitchen (strings,...values) { console.log(strings.raw) console.log(values) return ... } console.log(str) ```
3.es6为字符串提供的几个小方法
let str='今天是hige好日子,心想的事儿都能成'
 //1.判断是否是以...开头
 console.log(str.startsWith('今天'))//true //2.判断是否是以...结尾 console.log(str.endsWith('能成'))//true //3.判断是否包含... console.log(str.includes('心'))//true

四:函数相关

1.设置函数参数的默认值

function fn (x=1,y=2) {
            return [x,y] } console.log(fn())

2.es6里面的... 叫法有两个

1.展开操作符   spread    可以在一个数组或者一个对象里快速添加另一个数组的元素或者另一个对象的属性方法,同名属性会覆盖

       var fruit=['apple','banana']; var food=['meat',...fruit]; console.log(fruit); console.log(...fruit) console.log(food) var obj={ name:'xiu', age:13 } console.log(obj) console.log({x:1,...obj}) 2.剩余操作符 rest 多在函数里设置不确定数量的参数时使用 function lunch (meat,drink,...food) { console.log(meat) console.log(drink) console.log(food) console.log(...food) } lunch('beaf','cola','bread','baozi') 3.name属性 es6为函数增加了一个name属性,需要注意的是,匿名函数的name是引用的变量的名字,又赋值又有名字的函数name是函数自己的函数名 function myFn (argument) { } console.log(myFn.name)//myFn var yourFn=function(){ } console.log(yourFn.name)//yourFn var hisFn=function herFn(){ } console.log(hisFn.name)//herFn

4.es6新增了箭头函数这样的定义函数的方式,箭头前面的是函数的参数,多个参数可以用()包裹,没有参数也要写(),箭头后面的是函数的返回值,如果写成{}包裹的话,就是函数体,需要返回值的时候要return

var fn=a=>a+1; // function fn (a) { // return a+1; // } console.log(fn(5))//6 var fn2=(a,b)=>{ return a+b; } // function fn2(a,b){ // return a+b; // } console.log(fn2(1,2))//3

五:变量添加属性和方法

es6 觉得如果一个对象想拥有和一个变量的名字一样的键名,并且值为这个变量的值的属性的话,可以直接在键值对里直接写一个变量名就好, 如果想设置一个方法,可以直接写方法名(){}

let name='allen',
    age=13;

let person={ name, age } console.log(person) var laugh=()=>{alert('hahaha')} let xiu={ laugh, sayHello(name='美女'){alert(`${name},你好`)}, ...person } xiu.laugh(); xiu.sayHello(); xiu.sayHello('baobao');

六:es6中对象的属性名可以用变量的值去表示

let person={};

person.name='xiuxiu';

person.firstName='zhao';

person['second name']='wang'; let myname='third name' person[myname]='gao'; console.log(person)

七:几个Object的方法

1. Object.is方法,可以做神奇的相等比较,类似为安格拉小姐
console.log(+0==-0)//true console.log(+0===-0)//true console.log(NaN==NaN)//false console.log(NaN===NaN)//false console.log(Object.is(+0,-0))//false console.log(Object.is(NaN,NaN))//true
2.Object.assign。可以用来把某一个对象里面的属性复制另一个属性里,同名会覆盖,按照顺序
var person={};
Object.assign(person,
    {name:'zhaoxiu'},
    {name:'wangxiu'},
    {age:18}
)
console.log(person)//{name:wangxiu,age:18}
3.Object.prototype相关
var a= Object.create(b)//把b作为原型来创建一个对象a
Object.getPrototypeOf(a)//获取a的原型 Object.setPrototypeOf(a,c);把a的原型设置为c var wang={ getName(){ return '王' } } var li={ getName(){ return '李' } } var xiu=Object.create(wang); console.log(xiu.getName())//王 console.log(Object.getPrototypeOf(xiu)==wang)//true Object.setPrototypeOf(xiu,li); console.log(xiu.getName())//李 console.log(Object.getPrototypeOf(xiu)==li)//true

通过{}.prototype可以来设置原型,但是输出出来的却是__proto__,es6觉得,那就直接设置__proto__吧

var wang={
    getName(){
        return '王'
    }
}
var li={ getName(){ return '李' } } var xiu={ __proto__:wang } console.log(xiu.getName())//王 console.log(Object.getPrototypeOf(xiu)==wang)//true xiu.__proto__=li console.log(xiu.getName())//李 console.log(Object.getPrototypeOf(xiu)==li)//true

在对象的方法里可以使用它原型的方法和属性,这个时候在方法里用super来代表自己的原型

var wang={
    getName(){
        return '王'
    }
}
var xiu={ __proto__:wang, getFname(){ console.log(super.getName()) } } console.log(xiu) xiu.getFname()

八:class类

es6里引入了类的概念,可以通过class关键字来创建一个类,里面的contructor方法可以用来接受实例化时传入的参数,还可以在class里写一些自定义的方法,不需要加,哦

class person  {
constructor(name){
    this.name=name
}

say(){ console.log(this.name) } } var xiu=new person('xiu') console.log(xiu) //..... person name:"xiu" __proto__:Object constructor:person(name) say:say() __proto__:Object //............ xiu.say()///xiu

es6觉得获取属性和设置属性的这些操作可以专门用set和get关键字来定义

class person  {
    constructor(name){
        this.name=name; this.hobby=[]; } get gethobby(){ return this.hobby; } set sethobby(hobby){ return this.hobby.push(hobby); } } var xiu=new person('xiu') console.log(xiu.hobby) //[] console.log(xiu.gethobby) //[] console.log(xiu.sethobby='sing') //sing console.log(xiu.hobby) // ['sing'] console.log(xiu.gethobby)// ['sing']

static 可以设置一个这个类自己的静态方法,只有类可以调用,实例不可以调用

class person  {
    constructor(name){ this.name=name; } say(word){ console.log(word) } static superSay(word){ console.log(word) } } var xiu=new person('xiu'); xiu.say('hello') //person.say('hello')//error //xiu.superSay('hello')//error person.superSay('hello')

es6的class里,可以用extentds来进行继承class Student extends Person{ },但是如果父类通过constructor接受了参数,并且之类需要接受更多的参数,那么需要在子类的constructor里用super来给父类contructor传递参数,剩下的再自己使用

class Person {
    constructor(name,age){ this.name=name; this.age=age; } say(){ console.log(`${this.name},${this.age}`) } } new Person('xiu',18).say()//xiu,18 class Student extends Person{ constructor(name,age,sex){ super(name,age) this.sex=sex } } console.log(new Student('liu',13,'male'))

九:集合类型

  • 1.es6新增了Set这个集合类型,类似与数组,但是还是有不少区别,比如,Set里不能有重复元素,重复元素不报错但是也不会添加进去

    通过new Set()来创建。初始参数是字符串 其他的要报错,会把字符串拆开了作为元素

var _set=new Set('123')
      console.log(_set)//Set {"1", "2", "3"}

Set里不能有重复元素,重复元素不报错但是也不会添加进去

var _set2=new Set('1223')
     console.log(_set2)//Set {"1", "2", "3"}

通过add方法来添加新元素 并且新添加是什么类型就是什么类型

var _set3=new Set('123')
_set3.add(4) console.log(_set3)//Set {"1", "2", "3",4}
通过size来获取元素个数

        var _set4=new Set('123') console.log(_set4.size)//3 通过delete来删除元素 var _set5=new Set('123') _set5.delete('3') console.log(_set5)//Set {"1", "2"} 通过has来判断有没有这个元素 var _set6=new Set('123') console.log(_set6.has('3'))//true 可以通过forEach来遍历 var _set7=new Set('123') _set7.forEach((x,i)=>{ console.log(`${x},${i}`) }) // 1,1 // 2,2 // 3,3 通过clear来清除元素 var _set8=new Set('123') _set8.clear(); console.log(_set8)//Set {}

2.map,es6新增了map这样的类型,和{}的区别就是可以用任何数据类型作为键值

let map=new Map(); //获取一个map

        let [obj,fn,str]=[{},function () {},'hello']; map.set(obj,'obj') //设置map的键值对 map.set(fn,'fn') map.set(str,'str') console.log(map) console.log(map.size)//获取map的键值对个数 console.log(map.get(obj)) //获取map的键对应的值 console.log(map.delete(fn)); //删除某一个键值对 console.log(map.has(fn)) //检测是否包含某个键名 console.log(map.has(obj)) map.forEach((value,key)=>{ //可以用forEach来遍历map console.log(value) console.log(key) }) map.clear(); //清空map的键值对 console.log(map)

10.模块系统

在es6里引入了模块的概念

export function square(x) {
    return x * x;
}
import square from 'lib';
square(2)//4
export function square(x) {
    return x * x;
}
export function diag(x, y) { return sqrt(square(x) + square(y)); }
import { square, diag } from 'lib';
console.log(square(11)); // 121 console.log(diag(4, 3));
import * as lib from 'lib'; square = lib.square;



--------------------------------------------------------

被编辑器折腾到现在……
---------------------------------------------------------------2018/5/10/22:04

现在才写到正则表达式……


正则表达式

首先解决一个最基本的问题,什么是正则表达式?
首先是百度百科的解释: 正则表达式是对 字符 串操作的一种逻辑公式,就是用事先定义好的一些特定字符、及这些特定字符的组合,组成一个“规则字符串”,这个“规则字符串”用来表达对字符串的一种过滤逻辑。
给定一个正则表达式和另一个字符串,我们可以达到如下的目的:
1. 给定的字符串是否符合正则表达式的过滤逻辑(称作“匹配”):
2. 可以通过正则表达式,从字符串中获取我们想要的特定部分。

正则表达式的特点是:
1. 灵活性、逻辑性和功能性非常强;
2. 可以迅速地用极简单的方式达到字符串的复杂控制。
3. 对于刚接触的人来说,比较晦涩难懂。

晦涩难懂………… 晦涩难懂…… 晦……涩……难……懂……
你这么写当然晦涩难懂(╯‵□′)╯︵┻━┻

----------------------------------------------------------------------------------引用自 菜鸟教程
Python 自1.5版本起增加了re 模块,它提供 Perl 风格的正则表达式模式。

re 模块使 Python 语言拥有全部的正则表达式功能。

re.match函数

re.match 尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,match()就返回none。

函数语法

re.match(pattern, string, flags=0)

函数参数说明:

参数 描述
pattern 匹配的正则表达式
string 要匹配的字符串。
flags 标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。参见:正则表达式修饰符 - 可选标志

匹配成功re.match方法返回一个匹配的对象,否则返回None。

我们可以使用group(num) 或 groups() 匹配对象函数来获取匹配表达式。

匹配对象方法 描述
group(num=0) 匹配的整个表达式的字符串,group() 可以一次输入多个组号,在这种情况下它将返回一个包含那些组所对应值的元组。
groups() 返回一个包含所有小组字符串的元组,从 1 到 所含的小组号。

re.search方法

re.search 扫描整个字符串并返回第一个成功的匹配。

函数语法:

re.search(pattern, string, flags=0)

函数参数说明:

参数 描述
pattern 匹配的正则表达式
string 要匹配的字符串。
flags 标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。

匹配成功re.search方法返回一个匹配的对象,否则返回None。

我们可以使用group(num) 或 groups() 匹配对象函数来获取匹配表达式。

匹配对象方法 描述
group(num=0) 匹配的整个表达式的字符串,group() 可以一次输入多个组号,在这种情况下它将返回一个包含那些组所对应值的元组。
groups() 返回一个包含所有小组字符串的元组,从 1 到 所含的小组号。

re.match与re.search的区别

re.match只匹配字符串的开始,如果字符串开始不符合正则表达式,则匹配失败,函数返回None;而re.search匹配整个字符串,直到找到一个匹配。


检索和替换

Python 的 re 模块提供了re.sub用于替换字符串中的匹配项。

语法:

re.sub(pattern, repl, string, count=0, flags=0)

参数:

  • pattern : 正则中的模式字符串。
  • repl : 替换的字符串,也可为一个函数。
  • string : 要被查找替换的原始字符串。
  • count : 模式匹配后替换的最大次数,默认 0 表示替换所有的匹配

re.compile 函数

compile 函数用于编译正则表达式,生成一个正则表达式( Pattern )对象,供 match() 和 search() 这两个函数使用。

语法格式为:

re.compile(pattern[, flags])

参数:

  • pattern : 一个字符串形式的正则表达式

  • flags : 可选,表示匹配模式,比如忽略大小写,多行模式等,具体参数为:

    1. re.I 忽略大小写
    2. re.L 表示特殊字符集 \w, \W, \b, \B, \s, \S 依赖于当前环境
    3. re.M 多行模式
    4. re.S 即为 . 并且包括换行符在内的任意字符(. 不包括换行符)
    5. re.U 表示特殊字符集 \w, \W, \b, \B, \d, \D, \s, \S 依赖于 Unicode 字符属性数据库
    6. re.X 为了增加可读性,忽略空格和 # 后面的注释

findall

在字符串中找到正则表达式所匹配的所有子串,并返回一个列表,如果没有找到匹配的,则返回空列表。

注意: match 和 search 是匹配一次 findall 匹配所有。

语法格式为:

findall(string[, pos[, endpos]])

参数:

  • string : 待匹配的字符串。
  • pos : 可选参数,指定字符串的起始位置,默认为 0。
  • endpos : 可选参数,指定字符串的结束位置,默认为字符串的长度。

re.finditer

和 findall 类似,在字符串中找到正则表达式所匹配的所有子串,并把它们作为一个迭代器返回。

re.finditer(pattern, string, flags=0)

参数:

参数 描述
pattern 匹配的正则表达式
string 要匹配的字符串。
flags 标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。参见:正则表达式修饰符 - 可选标志

re.split

split 方法按照能够匹配的子串将字符串分割后返回列表,它的使用形式如下:

re.split(pattern, string[, maxsplit=0, flags=0])

参数:

参数 描述
pattern 匹配的正则表达式
string 要匹配的字符串。
maxsplit 分隔次数,maxsplit=1 分隔一次,默认为 0,不限制次数。
flags 标志位,用于控制正则表达式的匹配方式,如:是否区分大小写,多行匹配等等。参见:正则表达式修饰符 - 可选标志

正则表达式对象

re.RegexObject

re.compile() 返回 RegexObject 对象。

re.MatchObject

group() 返回被 RE 匹配的字符串。

  • start() 返回匹配开始的位置
  • end() 返回匹配结束的位置
  • span() 返回一个元组包含匹配 (开始,结束) 的位置

正则表达式修饰符 - 可选标志

正则表达式可以包含一些可选标志修饰符来控制匹配的模式。修饰符被指定为一个可选的标志。多个标志可以通过按位 OR(|) 它们来指定。如 re.I | re.M 被设置成 I 和 M 标志:

修饰符 描述
re.I 使匹配对大小写不敏感
re.L 做本地化识别(locale-aware)匹配
re.M 多行匹配,影响 ^ 和 $
re.S 使 . 匹配包括换行在内的所有字符
re.U 根据Unicode字符集解析字符。这个标志影响 \w, \W, \b, \B.
re.X 该标志通过给予你更灵活的格式以便你将正则表达式写得更易于理解。

正则表达式模式

模式字符串使用特殊的语法来表示一个正则表达式:

字母和数字表示他们自身。一个正则表达式模式中的字母和数字匹配同样的字符串。

多数字母和数字前加一个反斜杠时会拥有不同的含义。

标点符号只有被转义时才匹配自身,否则它们表示特殊的含义。

反斜杠本身需要使用反斜杠转义。

由于正则表达式通常都包含反斜杠,所以你最好使用原始字符串来表示它们。模式元素(如 r'\t',等价于 '\\t')匹配相应的特殊字符。

下表列出了正则表达式模式语法中的特殊元素。如果你使用模式的同时提供了可选的标志参数,某些模式元素的含义会改变。

模式 描述
^ 匹配字符串的开头
$ 匹配字符串的末尾。
. 匹配任意字符,除了换行符,当re.DOTALL标记被指定时,则可以匹配包括换行符的任意字符。
[...] 用来表示一组字符,单独列出:[amk] 匹配 'a','m'或'k'
[^...] 不在[]中的字符:[^abc] 匹配除了a,b,c之外的字符。
re* 匹配0个或多个的表达式。
re+ 匹配1个或多个的表达式。
re? 匹配0个或1个由前面的正则表达式定义的片段,非贪婪方式
re{ n} 精确匹配 n 个前面表达式。例如, o{2} 不能匹配 "Bob" 中的 "o",但是能匹配 "food" 中的两个 o。
re{ n,} 匹配 n 个前面表达式。例如, o{2,} 不能匹配"Bob"中的"o",但能匹配 "foooood"中的所有 o。"o{1,}" 等价于 "o+"。"o{0,}" 则等价于 "o*"。
re{ n, m} 匹配 n 到 m 次由前面的正则表达式定义的片段,贪婪方式
a| b 匹配a或b
(re) 匹配括号内的表达式,也表示一个组
(?imx) 正则表达式包含三种可选标志:i, m, 或 x 。只影响括号中的区域。
(?-imx) 正则表达式关闭 i, m, 或 x 可选标志。只影响括号中的区域。
(?: re) 类似 (...), 但是不表示一个组
(?imx: re) 在括号中使用i, m, 或 x 可选标志
(?-imx: re) 在括号中不使用i, m, 或 x 可选标志
(?#...) 注释.
(?= re) 前向肯定界定符。如果所含正则表达式,以 ... 表示,在当前位置成功匹配时成功,否则失败。但一旦所含表达式已经尝试,匹配引擎根本没有提高;模式的剩余部分还要尝试界定符的右边。
(?! re) 前向否定界定符。与肯定界定符相反;当所含表达式不能在字符串当前位置匹配时成功
(?> re) 匹配的独立模式,省去回溯。
\w 匹配字母数字及下划线
\W 匹配非字母数字及下划线
\s 匹配任意空白字符,等价于 [\t\n\r\f].
\S 匹配任意非空字符
\d 匹配任意数字,等价于 [0-9].
\D 匹配任意非数字
\A 匹配字符串开始
\Z 匹配字符串结束,如果是存在换行,只匹配到换行前的结束字符串。
\z 匹配字符串结束
\G 匹配最后匹配完成的位置。
\b 匹配一个单词边界,也就是指单词和空格间的位置。例如, 'er\b' 可以匹配"never" 中的 'er',但不能匹配 "verb" 中的 'er'。
\B 匹配非单词边界。'er\B' 能匹配 "verb" 中的 'er',但不能匹配 "never" 中的 'er'。
\n, \t, 等. 匹配一个换行符。匹配一个制表符。等
\1...\9 匹配第n个分组的内容。
\10 匹配第n个分组的内容,如果它经匹配。否则指的是八进制字符码的表达式。

正则表达式实例

字符匹配

实例 描述
python 匹配 "python".

字符类

实例 描述
[Pp]ython 匹配 "Python" 或 "python"
rub[ye] 匹配 "ruby" 或 "rube"
[aeiou] 匹配中括号内的任意一个字母
[0-9] 匹配任何数字。类似于 [0123456789]
[a-z] 匹配任何小写字母
[A-Z] 匹配任何大写字母
[a-zA-Z0-9] 匹配任何字母及数字
[^aeiou] 除了aeiou字母以外的所有字符
[^0-9] 匹配除了数字外的字符

特殊字符类

实例 描述
. 匹配除 "\n" 之外的任何单个字符。要匹配包括 '\n' 在内的任何字符,请使用象 '[.\n]' 的模式。
\d 匹配一个数字字符。等价于 [0-9]。
\D 匹配一个非数字字符。等价于 [^0-9]。
\s 匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]。
\S 匹配任何非空白字符。等价于 [^ \f\n\r\t\v]。
\w 匹配包括下划线的任何单词字符。等价于'[A-Za-z0-9_]'。
\W 匹配任何非单词字符。等价于 '[^A-Za-z0-9_]'。
------------------------------------------------------------------侵删
上面仅引用了语法规则,现在该解决最初的问题了,正则表达式到底是干啥的?
简而言之,就是折腾一个字符串,比如从里面拆点东西出来,顺手调一下格式哇之类的,估计跟爬虫什么的有点关系,不过,书上给的例子是用来处理电话号码簿。

好了,这些都是Python的内容,还是绕回JS上吧。

字符串的正则方法

字符串对象共有 4 个方法,可以使用正则表达式:match()replace()search()split()

ES6 将这 4 个方法,在语言内部全部调用RegExp的实例方法,从而做到所有与正则相关的方法,全都定义在RegExp对象上。

  • String.prototype.match 调用 RegExp.prototype[Symbol.match]
  • String.prototype.replace 调用 RegExp.prototype[Symbol.replace]
  • String.prototype.search 调用 RegExp.prototype[Symbol.search]
  • String.prototype.split 调用 RegExp.prototype[Symbol.split]
(大家看看,像不像像不像)

JavaScript 语言的正则表达式,只支持先行断言(lookahead)和先行否定断言(negative lookahead),不支持后行断言(lookbehind)和后行否定断言(negative lookbehind)。ES2018 引入后行断言,V8 引擎 4.9 版(Chrome 62)已经支持。

”先行断言“指的是,x只有在y前面才匹配,必须写成/x(?=y)/。比如,只匹配百分号之前的数字,要写成/\d+(?=%)/。”先行否定断言“指的是,x只有不在y前面才匹配,必须写成/x(?!y)/。比如,只匹配不在百分号之前的数字,要写成/\d+(?!%)/

/\d+(?=%)/.exec('100% of US presidents have been male')  // ["100"]
/\d+(?!%)/.exec('that’s all 44 of them')                 // ["44"]

上面两个字符串,如果互换正则表达式,就不会得到相同结果。另外,还可以看到,”先行断言“括号之中的部分((?=%)),是不计入返回结果的。

“后行断言”正好与“先行断言”相反,x只有在y后面才匹配,必须写成/(?<=y)x/。比如,只匹配美元符号之后的数字,要写成/(?<=\$)\d+/。”后行否定断言“则与”先行否定断言“相反,x只有不在y后面才匹配,必须写成/(?<!y)x/。比如,只匹配不在美元符号后面的数字,要写成/(?<!\$)\d+/

/(?<=\$)\d+/.exec('Benjamin Franklin is on the $100 bill')  // ["100"]
/(?<!\$)\d+/.exec('it’s is worth about €90')                // ["90"]

上面的例子中,“后行断言”的括号之中的部分((?<=\$)),也是不计入返回结果。

下面的例子是使用后行断言进行字符串替换。

const RE_DOLLAR_PREFIX = /(?<=\$)foo/g;
'$foo %foo foo'.replace(RE_DOLLAR_PREFIX, 'bar');
// '$bar %foo foo'

上面代码中,只有在美元符号后面的foo才会被替换。

“后行断言”的实现,需要先匹配/(?<=y)x/x,然后再回到左边,匹配y的部分。这种“先右后左”的执行顺序,与所有其他正则操作相反,导致了一些不符合预期的行为。

首先,后行断言的组匹配,与正常情况下结果是不一样的。

/(?<=(\d+)(\d+))$/.exec('1053') // ["", "1", "053"]
/^(\d+)(\d+)$/.exec('1053') // ["1053", "105", "3"]

上面代码中,需要捕捉两个组匹配。没有“后行断言”时,第一个括号是贪婪模式,第二个括号只能捕获一个字符,所以结果是1053。而“后行断言”时,由于执行顺序是从右到左,第二个括号是贪婪模式,第一个括号只能捕获一个字符,所以结果是1053

其次,“后行断言”的反斜杠引用,也与通常的顺序相反,必须放在对应的那个括号之前。

/(?<=(o)d\1)r/.exec('hodor')  // null
/(?<=\1d(o))r/.exec('hodor')  // ["r", "o"]

上面代码中,如果后行断言的反斜杠引用(\1)放在括号的后面,就不会得到匹配结果,必须放在前面才可以。因为后行断言是先从左到右扫描,发现匹配以后再回过头,从右到左完成反斜杠引用。

---------------------------------------------------------------2018/5/12/11:08
唉,汶川地震都过去十年了,记得那会还在上小学,刚巧我们那儿也在地正待上,从那以后学校就开始演习了。每次想到这里,都会想,如果早点开始演习,会不会有更多的人活下来呢。

明天是母亲节,提前预祝全天下所有的母亲节日快乐,喜乐平安,身体康健,事事顺遂,家庭和睦。
/*顺便遥祝近一千公里外的母亲、奶奶和阿婆节日快乐*/

猜你喜欢

转载自blog.csdn.net/Karen_Yu_/article/details/80258437
今日推荐