express复习 + jsonp复习 + Element对象复习 + RegExp复习

express

  • cnpm install express --save
  • cnpm install nodemon --save ----------------------- 更改js后,无需重新node......

const express = require('express');

const app = express();

// 静态资源
// http://localhost:3000/public/1.html能访问到静态资源
app.use('/public', express.static('./public/')); 



// 路由
app.get(function (req, res, next) { // 不写第一个参数路径时,相当于'/'
    console.log('1');
    next();
    res.send('ni hao');
});

app.get('/', function(req, res, next){ // next可以继续往下匹配
    console.log('1');
    next();
    res.send('ni hao');
});

app.get('/', function(rea,res){
    console.log('2')
})

app.get('/teacher/:id', function(req,res){
    res.send('teacher: ' + req.params.id + '没有next时,get方法,该路由匹配后,下面的路由就不会再匹配');
});

app.use('/teacher', function(req,res){
    res.send('app.use能匹配/teacher/下的子文件夹,而app.get post ...等不能')
})

app.use('/admin', function (req, res, next) {
    // GET 'http://www.example.com/admin/new'
    console.log(req.originalUrl); // '/admin/new'
    console.log(req.baseUrl); // '/admin'
    console.log(req.path); // '/new'
    next();
});


app.get(/^\/student\/(\d{9,9})$/, function(req,res) { //可以使用正则
    res.send('student:' + req.params[0]);
})

app.use(function(req,res){ // 都不匹配,就是404页面
    res.send('404')
})




app.listen(3000);









(一) JSONP

(1) 同源

所谓同源指的是三个相同

  • 协议
  • 域名
  • 端口 --------------( http默认端口80,https默认端口443 )

(2) 如果是非同源,受到的限制的三种行为?

  • 无法读取非同源网页的 Cookie,LocalStorage,IndexDB
  • 无法接触非同源网页的 DOM
  • 无法向非同源地址发送 AJAX 请求 ( 可以发送,当浏览器会决绝接受响应 )

(3) jsonp -- ( JSON with Padding )

  • JSONP(JSON with Padding)是数据格式JSON的一种“使用模式”
  • 凡是拥有 ”src” 这个属性的标签都拥有跨域的能力,如<script>、<img>、<iframe>
  • jsonp只能发送get请求
  • 原理:
    jsonp协议的一个要点就是允许用户传递一个callback 参数给服务端,然后服务端返回数据时会将这个callback参数作为函数名来包裹住JSON数据,这样客户端就可以随意定制自己的函数来自动处理返回数 据了。
  • script标签的src属性格式:
script标签的src属性格式


例如:
http://freegeoip.net/json/?callback=foo
  • 服务端返回一个函数,包裹住json:
JSONP看起来与JSON差不多,只不过是被包含在函数调用中的JSON
服务端返回一个函数,包裹住json


例如:
foo({ “name”: “Nicholas” });   


注意: 
这里的foo要和script中的src中的http://freegeoip.net/json/?callback=foo中的foo保持一致
  • 客户端完整请求
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title></title>
    <script>
        // 动态插入 script 标签到 html 中
        function addScriptTag(src) {
          var script = document.createElement('script');
          script.setAttribute("type","text/javascript");
          script.setAttribute('src', src);
          document.getElementsByTagName('head')[0].appendChild(script);
        }
        // 获取 jsonp 文件
        window.onload = function () {
          addScriptTag('http://example.com/ip?callback=foo');
        }
        // 执行本地的 js 逻辑,这个要跟获取到的 jsonp 文件的函数要一致
        function foo(data) {
          console.log('Your public IP address is: ' + data.ip);
        };
    </script>
</head>
<body>
</body>
</html>

https://segmentfault.com/a/1190000012967320

jsonp原理图.png











(二) Element对象

Element对象对应的是网页的HTML元素,每一个html元素在DOM树上会转化成Element节点对象

  • 元素节点的 ( nodeType ) 属性都是 ( 1 )
  • Element.id ---------------------- 获取元素节点的id属性 (getElementById,getAttribute() 等)
  • Element.tagname ------------- 获取元素的大写标签名 (nodeName等)
  • Element.draggable ----------- 元素节点是否可以被拖动,返回boolean,可读写
  • Element.lang ------------------- 返回当前元素的语言设置。该属性可读写。
  • Element.title -------------------- 用来读写当前元素的 HTML 属性title。该属性通常用来指定,鼠标悬浮时弹出的文字提示框。
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>Page Title</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <script type="text/javascript">
        window.onload = function() {
            var x = document.querySelector('p'); ---------------------- 获取p元素节点
            var xx = document.getElementById('p'); -------------------- 获取p元素节点
            console.log(x,xx);

            var y = x.id;  -------------------------------------------- 获取id属性节点的属性值
            var yy = x.getAttribute('id'); ---------------------------- 获取id属性节点的属性值
            console.log(y, yy)

            var z = x.tagName; ---------------------------- 获取元素节点的标签名
            var zz = x.nodeName; -------------------------- 获取元素节点的标签名
            console.log(z,zz)

            x.draggable = false; -------------------------- 元素节点是否可拖动
            x.lang="zh-cn"; ------------------------------- 返回当前元素的语言设置。该属性可读写。
            x.title = "hover时,element.title作为提示内容,pc上有效"; ----- hover时提示文字,pc有效
        }
    </script>
</head>
<body>
    <p id="p">p元素节点</p>
</body>
</html>
  • Element.attributes ------------ 返回一个类似数组的对象,成员是当前元素节点的所有属性节点
  • className属性 --------------- 用来读写当前元素节点的class属性。它的值是一个字符串,每个class之间用空格分割。
  • classList属性------------------- 返回一个类似数组的对象,当前元素节点的每个class就是这个对象的一个成员。
// HTML 代码 <div class="one two three" id="myDiv"></div>
var div = document.getElementById('myDiv');

div.className --------------------------- element.className返回class属性值 组成的字符串
// "one two three"

div.classList --------------------------- class属性值组成的类数组对象
// {
//   0: "one"
//   1: "two"
//   2: "three"
//   length: 3
// }
  • classList对象有下列方法:
add():增加一个 class。

remove():移除一个 class。

contains():检查当前元素是否包含某个 class。

toggle():将某个 class 移入或移出当前元素。

item():返回指定索引位置的 class。

toString():将 class 的列表转为字符串。



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



var div = document.getElementById('myDiv');

div.classList.add('myCssClass');
div.classList.add('foo', 'bar');
div.classList.remove('myCssClass');
div.classList.toggle('myCssClass'); // 如果 myCssClass 不存在就加入,否则移除
div.classList.contains('myCssClass'); // 返回 true 或者 false
div.classList.item(0); // 返回第一个 Class
div.classList.toString();

Element.innerHTML ---------- 所有子节点

  • Element.innerHTML属性返回一个 ( 字符串 ) ,等同于该元素包含的所有 HTML 代码。
  • 该属性可读写,常用来设置某个节点的内容。
  • 它能改写所有元素节点的内容,包括<HTML>和<body>元素。
  • 如果将innerHTML属性设为空,等于删除所有它包含的所有节点。
  • 注意:
    读取属性值的时候,如果文本节点包含&、小于号(<)和大于号(>),innerHTML属性会将它们转为实体形式&amp;、&lt;、&gt;
  • 如果想得到原文,建议使用element.textContent属性。
  • 写入的时候,如果插入的文本包含 HTML 标签,会被解析成为节点对象插入 DOM。注意,如果文本之中含有<script>标签,虽然可以生成script节点,但是插入的代码不会执行。

Element.outerHTML ---------- 包括元素本身和所有子节点

Element.outerHTML属性返回一个字符串,表示当前元素节点的所有 HTML 代码,包括该元素本身和所有子元素。

  • outerHTML属性是可读写的,对它进行赋值,等于替换掉当前元素。

// HTML 代码如下
// <div id="container"><div id="d">Hello</div></div>
var container = document.getElementById('container');
var d = document.getElementById('d');
container.firstChild.nodeName // "DIV"
d.nodeName // "DIV"

d.outerHTML = '<p>Hello</p>';    ------------------------- outerHTML可读写
container.firstChild.nodeName // "P"
d.nodeName // "DIV"


注意:
上面代码中,变量d代表子节点,它的outerHTML属性重新赋值以后,内层的div元素就不存在了,被p元素替换了。

但是,变量d依然指向原来的div元素,这表示被替换的DIV元素还存在于内存中。!!!!!!!!!!!!!!!

  • 注意,如果一个节点没有父节点,设置outerHTML属性会报错。

Element.clientHeight

Element.clientWidth

  • Element.clientHeight属性返回一个整数值,表示元素节点的 CSS 高度(单位像素)
  • 只对块级元素生效,对于行内元素返回0。
  • 如果块级元素没有设置 CSS 高度,则返回实际高度
  • 除了元素本身的高度,它还包括padding部分,但是不包括border、margin。
  • 如果有水平滚动条,还要减去水平滚动条的高度。
  • 这个值始终是整数,如果是小数会被四舍五入。

document.documentElement ----------------------- 的clientHeight属性,返回当前视口的高度(即浏览器窗口的高度),等同于window.innerHeight属性减去水平滚动条的高度(如果有的话)。

document.body ----------------------------------------- 的高度则是网页的实际高度。

一般来说,document.body.clientHeight大于document.documentElement.clientHeight。

Element.clientLeft

Element.clientTop

  • Element.clientLeft属性等于元素节点左边框(left border)的宽度(单位像素),不包括左侧的padding和margin。
  • 如果没有设置左边框,或者是行内元素(display: inline),该属性返回0。
  • 该属性总是返回整数值,如果是小数,会四舍五入。
  • Element.clientTop属性等于网页元素顶部边框的宽度(单位像素),其他特点都与clientTop相同。

Element.scrollHeight ------------ 当前元素的总高度

Element.scrollWidth

  • Element.scrollHeight属性返回一个整数值(小数会四舍五入),表示当前元素的总高度(单位像素)包括溢出容器当前不可见的部分
  • 它包括padding,但是不包括border、margin以及水平滚动条的高度(如果有水平滚动条的话)
  • 还包括伪元素(::before或::after)的高度。
  • Element.scrollWidth属性表示当前元素的总宽度(单位像素),其他地方都与scrollHeight属性类似。
  • 这两个属性只读。

整张网页的总高度可以从document.documentElement或document.body上读取。

Element.scrollLeft

Element.scrollTop

  • Element.scrollLeft属性表示当前元素的水平滚动条向右侧滚动的像素数量
  • Element.scrollTop属性表示当前元素的垂直滚动条向下滚动的像素数量
  • 对于那些没有滚动条的网页元素,这两个属性总是等于0
  • 这两个属性都可读写,设置该属性的值,会导致浏览器将当前元素自动滚动到相应的位置。

Element.offsetHeight

Element.offsetWidth

  • Element.offsetHeight属性返回一个整数,表示元素的 CSS 垂直高度(单位像素)
  • 包括元素本身的高度、padding 和 border,以及水平滚动条的高度(如果存在滚动条)
  • Element.offsetWidth属性表示元素的 CSS 水平宽度(单位像素),其他都与Element.offsetHeight一致。

Element.offsetLeft

Element.offsetTop

  • Element.offsetLeft返回当前元素左上角相对于Element.offsetParent节点的水平位移
  • Element.offsetTop返回垂直位移,单位为像素。通常,这两个值是指相对于父节点的位移

滚动到顶部案列 vue

<template>
  <div id="app">
    <div class="top" v-if="buttonShow" v-on:click="goTop">回到顶部</div>
    <router-view/>
  </div>
</template>

<script>
export default {
  name: 'App',
   data () {
    return {
     buttonShow: false,
    }
  },
  mounted() {
      document.addEventListener('scroll', this.goScroll)   ----- 页面加载完成,监听scroll事件
  },
  methods: {
   goScroll: function() {
      const currentTop = document.documentElement.scrollTop || document.body.scrollTop; 
      const viewPort = document.documentElement.clientHeight || document.body.clientHeight;
      console.log(currentTop, viewPort)
      if (currentTop > viewPort/2) {    ------------------------- 滚动的距离和释口距离比较
          this.buttonShow = true
      } else {
          this.buttonShow = false;
      }
   },
   goTop: function() {
     console.log('aa');
      let currentTop = document.documentElement.scrollTop || document.body.scrollTop; 
      const totalTime = 2000;   ---------------------- 总时间
      const frequent = 200; -------------------------- 频率,多长时间滚动一次
      const speed = currentTop/2000; ----------------- 滚动的速度
      const stepDistance = speed * frequent; --------- 一次滚动的距离

      let timer = setInterval(()=> {
        if (currentTop<=0) { ------------------------- 距离小于0时,停止滚动
          window.clearInterval(timer)
          return;
        }
        currentTop = currentTop - stepDistance;  ------ 当前距离 = 初始距离 - 一次滚动的距离
        document.documentElement.scrollTop = currentTop; -------- 设置当前距离滚动顶部的距离
      }, 20)  ----------------------------------------- 20毫秒执行一次以上操作


   }
  }
}
</script>

<style>
#app {
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
.top {
  background: yellow;
  padding:20px 40px;
  position: fixed;
  bottom: 100px;
  right: 10px;
}
</style>

滚动到顶部案列 react

import React,{Component} from 'react';



export default class toTOP extends Component {
    state = {
        buttonShow: false
    }
    componentWillMount() {
        window.addEventListener('scroll',this.onScroll)  // 监听滚动事件
    }
    onScroll = () => {
        var currentTop = document.documentElement.scrollTop || document.body.scrollTop;   // 顶部到最顶部的距离
        var viewPortHeight = document.documentElement.clientHeight || document.body.clientHeight;  // 可视高度
        
        if ( currentTop > viewPortHeight) {  // 大于显示按钮
            this.setState({
                buttonShow:true
            })
        } else {
            this.setState({ // 小于隐藏按钮
                buttonShow: false
            })
        }
    }
    goTop = () => {
        var currentTop = document.documentElement.scrollTop || document.body.scrollTop;
        var totalTimes = 200;
        var speed = currentTop/totalTimes ;
        var StepTime = 10;
        var setpDistance = speed * StepTime;

        var timer = window.setInterval(()=>{     // var itmer = setInterval()也可以,不要window
            if ( currentTop <=0 ) {
                window.clearInterval(timer);
                return;
            }
            currentTop = currentTop - setpDistance;
            document.documentElement.scrollTop = currentTop;
            document.body.scrollTop = currentTop;
        },StepTime)
        
    }
    render() {
        return (
            <div >
                <div>
                    回到顶部测试
                </div>

                <div 
                ref="button"  
                onClick={this.goTop}
                style={
                    this.state.buttonShow
                    ?
                    {
                        display:'inline-block',
                        border:'1px solid red',
                        background:'yellow',
                        padding:'10px 30px',
                        position:'fixed',
                        bottom:'60px',
                        right:'20px'
                    }
                    :
                    {
                        display:'none',
                        border:'1px solid red',
                        background:'yellow',
                        padding:'10px 30px',
                        position:'fixed',
                        bottom:'60px',
                        right:'20px'
                    }
    
                }>
                    回到顶部
                </div>


                <div style={{padding:'20px 160px'}}>
                年参演电视剧《与青春有关的日子》,开始在影视圈崭露头角[1]  。2005年拍摄古装剧《锦衣卫》。2007年主演赵宝刚导演的青春剧《奋斗》;[2]  同年,主演首部电影《走着瞧》。2008年主演滕华涛执导的电视剧《蜗居》,饰演80后城市青年小贝。[1]  2009年,在电影《海洋天堂》中扮演自闭症患者王大福;同年参演抗战题材的电视剧《雪豹》[4]  。2011年,主演的电视剧《裸婚时代》在各大卫视播出;[5]  2011年-2012年连续2年获得北京大学生电影节[6-7]  最受大学生欢迎男演员奖。2012年,凭借电影《失恋33天》获得第31届大众电影百花奖最佳男主角奖;[8]  同年成立自己经营的北京君竹影视文化有限公司,并导演第一部影视作品《小爸爸》。2013年2月,主演的电影《西游·降魔篇》在全国上映。[9]  
2014年3月28日,主演的中韩合资文艺爱情片《我在路上最爱你》在全国上映。2014年12月18日,在姜文执导的动作喜剧片《一步之遥》中扮演武七一角。[10]  2016年,主演电视剧《少帅》,饰演张学良[11]  ;主演电视剧《剃刀边缘》[12]  。7月15日导演的电影《陆垚知马俐》上映。[13]  
演艺事业外,文章也参与公益慈善事业,2010年成立大福自闭症关爱基金。
2017年9月16日,凭借《陆垚知马俐》获得第31届中国电影金鸡奖导演处女作奖。[14]  

关于你。就是因为我的害怕,我亲眼看你走向她。我喜欢你是事实,你有女朋友也是事实。我以为我不说出口就会保持这样的朋友关系,却还是她赶了个巧,那应该是个寒假,你有女朋友了,我还是听说,我那么爱,却还是无果。于是我和她之间就莫名其妙的就多少有了敌人的感觉,或许就是别人口中的那样,世界上完全不相干的两个女人,会因为一个男人要么很友好,要么是仇恨。关于她我做不到友好,但也不是仇恨,只是你选择了她,我就希望她好好爱你,照顾你,连我的份也一起爱了。自爱上你的那天起,思念便成了戒不掉的瘾。你的一言一笑,一颦一蹙,无不牵动我的心,百千尘思,唯念一缕;万千红颜,唯恋一人。我愿意一生漂泊浪迹在你的故事里,甘愿为你鞍前马后,马首是瞻,即使你从未给我一句承诺,即使你从未给我半分爱情,依然无悔无怨。
   关于你。一场高考,考散了我们,毕业了会不会就是终生最后一见,很高兴,我们不是。各奔东西了,你们继续上了大学,值得欣慰的是,你们也是异地,这样不能算是我心机,只能说是恰巧,你们的安排恰合我意。后来也有听说,她从她的城市去看你,而那时的我能说什么呢。她是真心爱你,这是事实。我也曾和闺蜜说过,一生至少该有一次,为了某个人而忘了自己,不求有结果,不求同行,不求曾经拥有,甚至不求你爱我,只求在我最美的年华里,遇到你。今生遇见你,我觉得是幸福的,尽管这幸福交杂着万般痛苦。我也曾幻想着悄悄地去到你的学校,在某个阳光明媚的下午,在你去教室的路上和你来场偶遇,精心准备的偶遇,。可是我还来不及去和你偶遇,你们就毕了业。爱是种很玄的东西,说不清,道不明,剪不断,理还乱。世上,有种爱明知没有结果,却依然坚守原地,不舍离去,哪怕握不住你的一丝余温,依然选择默默为你守候。一路来去,心门只为你独开,山城只为你独驻,白天只为你旖旎,黑夜只为你流连。因为爱你,哪怕心入住荒岛,还是会以最深情的眼神,看着你幸福。
                </div>
               
            </div>
        )
    }
}









语句

语句 statement 是为了完成某种任务而进行的操作

  • 语句以分号结尾,一个分号就表示一个语句结束
  • 多个语句,可以写在一行内
  • 分号前面可以没有任何内容,js将其视为空语句

表达式

表达式 expression 为了得到返回值的计算式

  • 凡是预期为值得地方,都可以使用表达式

表达式和语句的区别

  • 语句是为了进行某种操作,一般不需要返回值
  • 表达式式为了得到返回值,一定有返回值
表达式和语句总结:
(1) 语句是为了完成某种任务进行得操作,一般不需要返回值
(2) 语句以分号结尾,分号前面可以没有任何内容,是空语句
(3) 多个语句可以写在一行内
(4) 表达式是为了得到返回值得计算值,一定有返回值,凡是预期为值的地方,都可以使用表达式


var a = 1 + 3 ; var b = 'abc';  ------------- 语句以分号结尾,两个语句可以写在一行内
;;; ----------------------------------------- 空语句,分号前面可以没有任何内容,js视其为空语句
1+3 在等号右边,预期是个值,所以可以使用表达式(为了得到返回值的计算式)

变量

变量是对值得具名引用

  • 变量就是为值取名,-------引用这个名字,就是引用这个值
  • 变量名:变量的名字就是变量名
  • 变量名区分大小写 ( A和a是两个不同的变量 )
  • 如果只是声明变量,而没有赋值,那么变量的值是 undefined
  • 如果变量赋值的时候,忘了写var命令,这条语句也是有效的。
  • 可以在同一条var命令中声明多个变量。
  • js是动态语言,变量的类型没有限制,变量可以随时更改类型
  • 如果使用var重新声明一个已经存在的变量,是无效的,但是,如果第二次声明的时候还进行了赋值,则会覆盖掉前面的值。

变量提升

js引擎的工作方式:先解析代码,获取所有被声明的变量,再一行一行的执行,造成造成的结果就是所有变量的声明语句,都会被提升到代码头部,这就叫做 ----- 代码提升hoisting -----

console.log(a);
var a = 1;   --------------------- 变量提升,变量的声明语句会被提升到代码头部,注意不包括赋值语句

等同于

var a;
console.log(a); -------------------- a是undifined,不会报错
a = 1;

标识符

标识符identifier: 用来识别各种值得合法名称

  • 最常见的表示符,------变量名和函数名
  • 标识符的命名规则:
第一个字符,可以是任意 Unicode 字母(包括英文字母和其他语言的字母),以及美元符号($)和下划线(_)。
第二个字符及后面的字符,除了 Unicode 字母、美元符号和下划线,还可以用数字0-9。



第一个字符:字母,$,下划线
第二个字符:字母,数字,$,下划线
  • 中文是合法的标识符,可以用作变量名。

注释

  • 一种是单行注释,用//起头;
  • 另一种是多行注释,放在/**/之间。

区块

JavaScript 使用大括号,将多个相关的语句组合在一起,称为“区块”(block)。

  • 区块:大括号包裹的多个语句
  • 对于var命令来说,区块不构成单独的作用域scop,与不使用区块没有任何区别
  • 单独使用区块不常见,区块一般用来构成复杂的语法结构,如for,while,if,funcion等
{
  var a = 1;
}

a // 1

if结构


if (m === 3) ------------------------- 只有在m等于3时,才会将其值加上1

m = m + 1; -------------------------- 只有一个语句时,可以不用 { }

break语句和continue语句

  • break语句用于跳出代码块或循环。
  • continue语句用于立即终止本轮循环,返回循环结构的头部,开始下一轮循环。



数据类型

number,string,boolean,null,undefined,object,symbol

如何确定一个值是什么类型 ( 三种方法 )

  • typeof ---------------------------------- 有6种返回值
  • instanceof ----------------------------- 主要用于对象,数组的区分
  • object.prototype.toString

typeof

  • typeof返回的是一个字符串,注意是一个字符串
  • 数值、字符串、布尔值分别返回number、string、boolean。
  • 函数返回function
  • undefined返回undefined
  • 对象返回object
  • 数组返回object
  • null返回object
  • typeof是个一元运算符,运算时具有较高的优先级

(1) es5有6种数据类型, typeof返回也是6种类型
---------- es5的6种数据类型:number, string, boolean, undefined, null, object
---------- typeof返回的6种类型:number, string, boolean, undefined, object, function




(2) typeof无法区分数组和对象
----------- 数组和对象可以通过 instanceof 来区分

var o = {};
var a = [];
o instanceof Array // false
a instanceof Array // true




(3) Number
Number(null) ------------------------- 0
Number(undefined) -------------------- NaN
Number('') --------------------------- 0
Number(true) ------------------------- 0
5 + null ----------------------------- 5
5 + undefined ------------------------ NaN




(4) typeof NaN ----------------------- 'number'
注意 typeof 返回的是一个字符串
NaN不等于任何值,包括自身
数组的indexOf方法内部使用的是严格相等运算符,所以该方法对NaN不成立。
[NaN].indexOf(NaN) // -1


(5) typeof是一元运算符,具有较高的运算优先级

    typeof 1 !== 'undefined' 
    运算顺序是:
    1.    typeof 1  ----------------------------- 结果是 number
    2.    'number' !== 'undefined' -------------- 结果是true


typeof ( 1 !==  'number' );    -----------------------  结果是 'boolean'
typeof 1 !== 'number'          -----------------------  结果是 false

与数值相关的全局方法

parseInt(字符串,值的进制)

parseInt() 用于将 ( 字符串 ) 转化为 ( 整数 )

  • 如果字符串头部有空格,空格会被自动去除。
  • 如果parseInt的参数不是字符串,则会先转为字符串再转换。
  • 字符串转为整数的时候,是一个个字符依次转换,如果遇到不能转为数字的字符,就不再进行下去,返回已经转好的部分。
  • 如果字符串的第一个字符不能转化为数字(后面跟着数字的正负号除外),返回NaN。
  • 所以,parseInt的返回值只有两种可能,要么是一个十进制整数,要么是NaN。
  • 如果字符串以0开头,将其按照10进制解析。
  • 参数:
    parseInt方法还可以接受第二个参数(2到36之间),表示被解析的值的进制,返回该值对应的十进制数。
  • 如果第二个参数是0、undefined和null,则直接忽略
parseInt(1.23) // 1
// 等同于
parseInt('1.23') // 1
// 也等同于
parseInt(' 1.23') // 1
参数

parseInt('1000', 2) -------------------- 表示将2进制的字符串1000,转换成十进制整数

parseFloat()

  • 如果参数不是字符串,或者字符串的第一个字符不能转化为浮点数,则返回NaN。
  • 区别Number()函数
parseFloat(true)  // NaN
Number(true) // 1

parseFloat(null) // NaN
Number(null) // 0

parseFloat('') // NaN
Number('') // 0

parseFloat('123.45#') // 123.45
Number('123.45#') // NaN

isNaN()

isNaN方法可以用来判断一个值是否为NaN

  • isNaN只对数值有效,如果传入其他值,会被先转成数值。
  • 比如,传入字符串的时候,字符串会被先转成NaN,所以最后返回true。
    也就是说,isNaN为true的值,有可能不是NaN,而是一个字符串。
  • 出于同样的原因,对于对象和数组,isNaN也返回true。
  • 但是,对于空数组和只有一个数值成员的数组,isNaN返回false。


isNaN('Hello') // true
// 相当于
isNaN(Number('Hello')) // true ---------------------------- Number('hello')值是NaN




class类

  • 类的constructor()方法就是构造函数
  • 定义类的方法的时候,前面不需要加 ( function ) 关键字
  • 类的方法之间,不需要 ( 逗号 ) 分隔,加了逗号会报错
  • es6的类,可以看作是构造函数的另一种写法,类的数据类型是'function',类本身就指向构造函数,使用时,也是通过new命令生成实例,类的所有方法都是定义在类的prototype属性上面 ------------------------- 重要
  • 类的内部所有定义的方法,都是不可枚举的(non-enumerable)。
  • 类的属性名,可以采用表达式。( 为了得到返回值的计算式是 表达式 )
  • 类和模块的内部,默认就是严格模式,所以不需要使用use strict指定运行模式。
  • 实例的属性除非显式定义在自身,即this对象上,否则都是定义在原型上
  • 类的实例可以共享一个原型对象,原型链继承
class Point {
   doStuff() {
    console.log('stuff');
   }
}

var b = new Point ();
b.doStuff() // "stuff"

typeof Point // "function"
Point === Point.prototype.constructor // true




// 等同于
Point.prototype = {
  doStuff() {},
};

constructor方法

一个类必须有constructor方法,如果没有显式定义,一个空的constructor方法将会被默认添加

class表达式

与函数一样,类也可以使用表达式的形式定义

类不存在变量提升

class静态方法

类相当于实例的原型,所有在类中定义的方法,都会被实例所继承

  • 如果在类的方法前加上 static 关键字,就表示该方法不会被实例所继承,而是直接通过类来调用,这就成为静态方法
  • 静态方法: 在方法前加上 static 关键字,表示该方法不会被类的实例所继承,而是直接通过类来调用
  • 注意,如果静态方法包含this关键字,这个this指的是类,而不是实例。
  • 静态方法可以和非静态方法重名
  • 父类的静态方法,可以被子类继承。
  • 静态方法也是可以从super对象上调用的。
class AAA{
    static go() {
        console.log('aaaa')
    }
};

const BBB = new AAA(); 
BBB.go()  --------------------- Uncaught TypeError: BBB.go is not a function
AAA.go()  --------------------- aaaa



解析:
(1) 在类中定义的方法,都会被类的实例所继承
(2) 但是在方法前加上 static 关键字后,该方法是静态方法,不会被实例所继承,而是直接通过类本身调用
class Foo {
  static bar () {  -------------------------- 静态方法中的this指的是类,而不是实例
    this.baz();  ---------------------------- 静态方法不被实例所继承
  }
  static baz () {
    console.log('hello');
  }
  baz () {  --------------------------------- 静态方法可以和非静态方法重名
    console.log('world');  ------------------ 非静态方法,被实例所继承
  }
}
Foo.bar() // hello



class Bar extends Foo {   ------------------- 父类得静态方法,能被子类所继承
}
Bar.bar() // 'hello'
class Foo {
  static classMethod() {
    return 'hello';
  }
}

class Bar extends Foo {
  static classMethod() {
    return super.classMethod() + ', too';  ----------------- super在静态方法中表示父类
  }
}

Bar.classMethod() // "hello, too"

class的静态属性和实例属性

静态属性指的是class本身的属性,而不是定义在实例对象上的 ( this ) 属性

  • 静态属性
class Foo {
}
Foo.prop = 1;
Foo.prop // 1



提案新写法:
class MyClass {
  static myStaticProp = 42;   ---------------------------- 静态属性
  constructor() {
    console.log(MyClass.myStaticProp); // 42
  }
}
  • 实例属性
    以前,定义实例属性,只能写在类的constructor方法里面。
    有了新的写法以后,可以不在constructor方法里面定义。
class ReactCounter extends React.Component {
  constructor(props) {
    super(props);
    this.state = {    --------------------- 在类的constructor构造函数中,定义实例属性
      count: 0
    };
  }
}
class ReactCounter extends React.Component {
  state = {
    count: 0
  };
}
  • 静态属性和实例属性总结
class MyClass {
  myProp = 42;     --------------------------------- 类的实例属性
  static myStaticProp = 42; ------------------------ 类的静态属性
  static   constructor() {
    console.log(this.myProp); // 42 
    console.log(MyClass.myStaticProp); // 42
  }
}



class继承

  • class通过 extends 关键字实现继承
  • 子类必须在constructor中调用super方法,否则新建实例时会报错。因为子类的自己的this对象,必须通过父类的构造函数完成塑造,得到与父类同样是实例属性和方法,然后对其加工,得到子类自己的实例属性和方法。
  • 如果不调用super方法,就得不到this对象
  • 在子类的constructor中,只有先调用 super 方法后,才能使用 this 关键字
  • 父类的静态方法,被子类所继承,但是不被实例所继承
  • Object.getPrototypeOf方法可以用来从子类上获取父类。

super关键字

super关键字,可以当函数,也可以当对象

super作为函数

super作为函数调用时,代表父类的构造函数

  • super为函数时,虽然代表父类的构造函数,但是 ( 返回 ) 的是 ( 子类的实例 )!!!!!
  • super为函数时,只能用在子类的 constructor 中,用在其他地方会报错

super作为对象

super作为对象,在普通方法中指父类的原型对象

super作为对象时,用在普通方法中表示父类的原型对象,用在静态方法中,表示父类。

class A {
  p() {      ----------------------- 类的实例方法,是定义在类的原型上的
    return 2;
  }
}
class B extends A {
  constructor() {
    super();
    console.log(super.p()); -------- super作为对象,在普通方法中,表示父类的原型对象  //结果是2
  }
}
let b = new B();
  • 这里需要注意,由于super指向父类的原型对象,所以定义在父类实例上的方法或属性,是无法通过super调用的。
class A {
  constructor() {
    this.p = 2;
  }
}

class B extends A {
  get m() {
    return super.p; 
  } ----------------super作为对象,表示父类的原型对象,所以定义在父类实例上的属性和方法无法通过super调用
}

let b = new B();
b.m // undefined
  • 如果方法和属性定义在父类的原型对象上,super可以取到
class A {}
A.prototype.x = 2;

class B extends A {
  constructor() {
    super();
    console.log(super.x) // 2
  }
}

let b = new B();
  • ES6规定,在子类普通方法中,通过super调用父类的原型对象上的方法(父类的方法)时,方法内部的this,指向 ( 当前 ) 的 ( 子类实例 ) !!!!!!!!!!!
class A {
  constructor() {
    this.x = 1;
  }
  print() {
    console.log(this.x);----------(3) this指类的实例
  }
}

class B extends A {
  constructor() {
    super();
    this.x = 2;
  }
  m() {
    super.print();--(2) 指A中的print(),但是方法中的this,指向当前子类实例,this指函数调用时所在的对象
  }
}

let b = new B();
b.m() // 2   ---------------------(1) b.m()即B中的m()
  • 由于this指向子类实例,所以如果通过super对某个属性赋值,这时super就是this,赋值的属性会变成子类实例的属性。
class A {
  constructor() {
    this.x = 1;
  }
}

class B extends A {
  constructor() {
    super();
    this.x = 2;
    super.x = 3;  ----------------------- 通过super对某个属性赋值,super.x === this.x
    console.log(super.x); --------------- 读取super.x的时候,读的是A.prototype.x,所以返回undefined
    console.log(this.x); // 3
  }
}

let b = new B();

super作为对象,在静态方法中,指父类

class Parent {
  static myMethod(msg) {
    console.log('static', msg);
  }

  myMethod(msg) {
    console.log('instance', msg); ---------- 父类原型上的方法
  }
}

class Child extends Parent {
  static myMethod(msg) {
    super.myMethod(msg);--------------- super在静态方法中表示父类,父类直接调用,父类的静态方法
  }

  myMethod(msg) {
    super.myMethod(msg);   -------------- 原型链上的方法,super在普通方法中,表示父类的原型
  }
}

Child.myMethod(1); // static 1 ------------ 通过类直接调用,静态方法

var child = new Child();
child.myMethod(2); // instance 2  --------- 实例上调用,原型链方法
  • 在子类的静态方法中通过super调用父类的方法时,方法内部的this指向当前的子类,而不是子类的实例。
class A {
  constructor() {
    this.x = 1;
  }
  static print() {
    console.log(this.x);    ---------------------------- this指向B, B.x时B的静态属性
  }
}

class B extends A {
  constructor() {
    super();
    this.x = 2;
  }
  static m() {
    super.print();
  }
}

B.x = 3;    -------------------------------------------- B的静态属性x
B.m() // 3  -------------------------------------------- 结果是3


解析:
静态方法B.m里面,super.print指向父类的静态方法print()。这个方法里面的this指向的是B,而不是B的实例。
  • 注意,使用super的时候,必须显式指定是作为函数、还是作为对象使用,否则会报错。

类的prototype属性和__ proto__属性

Class 作为构造函数的语法糖,同时有prototype属性和 __ proto__属性,因此同时存在两条继承链。
(1)子类的__ proto__属性,表示构造函数的继承,总是指向父类。
(2)子类prototype属性的__ proto__属性,表示方法的继承,总是指向父类的prototype属性。

lass A {
}

class B extends A {
}

B.__proto__ === A // true 
B.prototype.__proto__ === A.prototype // true


解析:
(1) 子类.__proto__ === 父类
(2) 子类.prototype.__proto__ === 父类.prototype
  • 这样的结果是因为,类的继承是按照下面的模式实现的
class A {
}

class B {
}

// B 的实例继承 A 的实例
Object.setPrototypeOf(B.prototype, A.prototype);---------> B.prototype.__proto__ === A.prototype

// B 继承 A 的静态属性
Object.setPrototypeOf(B, A);   --------------------------> B.__proto__ === A

const b = new B();
  • 这两条继承链,可以这样理解:
    (1) 作为一个对象,子类(B)的原型(__ proto__属性)是父类(A);
    (2) 作为一个构造函数,子类(B)的原型对象(prototype属性)是父类的原型对象(prototype属性)的实例。

Object.create(A.prototype);   --------------------- 以A.prototype为原型,创建实例对象
// 等同于
B.prototype.__proto__ = A.prototype;

  • extends关键字后面可以跟多种类型的值。

class B extends A {
}

上面代码的A,只要是一个有prototype属性的函数,就能被B继承。

由于函数都有prototype属性(除了Function.prototype函数),因此A可以是任意函数。










regexp

字符串有四种与正则有关:
match(),search(),replace(),split()

  • regular expression 正则表达式
  • 新建正则表达式有两种方法:
  1. 字面量: 以斜杠表示开始和结束
  2. RegExp构造函数
  • 字面量方式和RegExp方式的区别:
  1. 字面量--------------------- 编译时新建,效率高
  2. new Regexp() ----------- 运行时新建,效率低
var regex = /xyz/;   ---------------------------------- 字面量方式,以斜杠表示开始和结束

var regex = new RegExp('xyz');  ----------------------- RegExp构造函数
  • RegExp()可以有两个参数,第一个是正则字符串,第二个表示修饰符
var regex = new RegExp('xyz', 'i'); ---------------- i 是 ignoreCase 的缩写, 表示忽略大小写
// 等价于
var regex = /xyz/i;

正则对象的实例属性

  1. RegExp.prototype.ignoreCase:返回一个布尔值,表示是否设置了 ( i ) 修饰符。
  2. RegExp.prototype.global:返回一个布尔值,表示是否设置了 ( g ) 修饰符。
  3. RegExp.prototype.multiline:返回一个布尔值,表示是否设置了 ( m ) 修饰符。
    上面三个属性都是只读的。
  4. RegExp.prototype.lastIndex:返回一个数值,表示下一次开始搜索的位置。
    该属性可读写,但是只在进行连续搜索时有意义,详细介绍请看后文。
  5. RegExp.prototype.source:返回正则表达式的字符串形式(不包括反斜杠),该属性只读。
var r = /abc/igm;

r.ignoreCase // true
r.global // true
r.multiline // true
r.lastIndex  --------------------------   0    lastIndex返回一个数值,表示下一次开始搜索的位置
r.source    --------------------------- "abc"  source返回正则表达式的字符串形式,只读   

正则表示式的实例方法

RegExp.prototype.test()

  • 正则实例对象的test方法返回一个布尔值,表示当前模式是否能匹配参数字符串
  • 如果正则表达式带有g修饰符,则每一次test方法都从上一次结束的位置开始向后匹配。
  • 带有g修饰符时,可以通过正则对象的lastIndex属性指定开始搜索的位置。
var r = /x/g;
var s = '_x_x';

r.lastIndex // 0  ------------------- 从0开始匹配
r.test(s) // true  ------------------ 匹配

r.lastIndex // 2 ------------------- 下一次从2位置开始匹配
r.test(s) // true ------------------ 匹配

r.lastIndex // 4
r.test(s) // false
  • 如果正则模式是一个空字符串,则匹配所有字符串。
new RegExp('').test('abc')
// true

RegExp.prototype.exec()

1. exec()匹配成功返回数组,匹配失败返回null
2. 数组成员包括,整个匹配成功的字符串,input,index
3. 正则带有括号,数组有多个成员,第一个是整个匹配,第二个是第一个括号的匹配结果,第三个成员是第二个括号匹配的结果
4. 正则带有g修饰符,则exec()可以执行多次

正则实例对象的exec方法,用来返回匹配结果。如果发现匹配,就返回一个数组,成员是匹配成功的子字符串,否则返回null。

  • 匹配成功,exec()返回数组,成员是匹配成功的子字符串
  • 匹配失败,exec()返回null
  • exec方法的返回数组还包含以下两个属性:
  1. input:整个原字符串。
  2. index:整个模式匹配成功的开始位置(从0开始计数)。
  • 如果正则表示式包含圆括号(即含有“组匹配”),则返回的数组会包括多个成员。
  1. 第一个成员是整个匹配成功的结果,
  2. 后面的成员就是圆括号对应的匹配成功的组。
    也就是说,
    第二个成员对应第一个括号,
    第三个成员对应第二个括号,
    以此类推。整个数组的length属性等于组匹配的数量再加1。

var a = /a(a)(b)/;    ---------------------- 如果正则带有括号,exec()返回的数组就包括多个成员
var b = 'aababacad';

var d = a.exec(b);
console.log(d)

结果是: ["aab", "a", "b", index: 0, input: "aababacad"]
第一个成员: 整个匹配的结果
第二个成员: 第一个括号匹配的结果
第三个成员: 第二个括号匹配的结果

  • 如果正则表达式加上g修饰符,则可以使用多次exec方法,下一次搜索的位置从上一次匹配成功结束的位置开始。
var reg = /a/g;
var str = 'abc_abc_abc'

var r1 = reg.exec(str);
r1 // ["a"]
r1.index // 0
reg.lastIndex // 1

var r2 = reg.exec(str);
r2 // ["a"]
r2.index // 4
reg.lastIndex // 5

var r3 = reg.exec(str);
r3 // ["a"]
r3.index // 8
reg.lastIndex // 9

var r4 = reg.exec(str);
r4 // null
reg.lastIndex // 0

String.prototype.match()

  • 匹配成功返回一个数组,匹配失败返回null。
  • 当正则带有g修饰符时,返回所有匹配成功的结果
  • 设置正则表达式的lastIndex属性,对match方法无效,匹配总是从字符串的第一个字符开始。
重要

var s = 'abba';
var r = /a/g;

s.match(r) // ["a", "a"] ----------------- string.match(正则带有g修饰符时),返回所有匹配成功的结果
r.exec(s) // ["a"]  ---------------------- exec()返回匹配成功的子字符串


注意:
1. exec()和match()的区别: 成功时,都返回数组,但match()正则表达式参数中有g修饰符,返回所有匹配成功的结果
2. 设则正则的lastIndex属性,对match()无效,match()总是从第一个字符开始匹配
var r = /a|b/g;
r.lastIndex = 7;
'xaxb'.match(r) // ['a', 'b']
r.lastIndex // 0

String.prototype.search()

--------------- 返回正则匹配结果在字符串中的位置
  • 区别 indexOf 方法:
  • search()的参数必须是正则表达式,而indexOf()的参数只是普通字符串, indexOf效率更高
  • 字符串对象的search方法,返回第一个满足条件的匹配结果在整个字符串中的位置。
  • 如果没有任何匹配,则返回-1。

String.prototype.replace()

  • 字符串对象的replace方法可以替换匹配的值。它接受两个参数,第一个是正则表达式,表示搜索模式,第二个是替换的内容。
  • 正则表达式如果不加g修饰符,就替换第一个匹配成功的值,否则替换所有匹配成功的值。

'aaa'.replace('a', 'b') // "baa"
'aaa'.replace(/a/, 'b') // "baa"

'aaa'.replace(/a/g, 'b') // "bbb"  --------------- 正则带有g修饰符,替换所有匹配成功的值

  • replace方法的一个应用,就是消除字符串首尾两端的空格。

String.prototype.split()

  • 字符串对象的split方法按照正则规则分割字符串,返回一个由分割后的各个部分组成的数组。
  • 该方法接受两个参数,第一个参数是正则表达式,表示分隔规则,第二个参数是返回数组的最大成员数。
// 非正则分隔
'a,  b,c, d'.split(',')
// [ 'a', '  b', 'c', ' d' ]

// 正则分隔,去除多余的空格 --------------------------------- 重要
'a,  b,c, d'.split(/, */)
// [ 'a', 'b', 'c', 'd' ]

// 指定返回数组的最大成员
'a,  b,c, d'.split(/, */, 2)
[ 'a', 'b' ]

匹配规则

字面量字符和元字符

  • 如果在正则表达式之中,某个字符只表示它字面的含义,那么它们就叫做
    “字面量字符”(literal characters)
  • 除了字面量字符以外,还有一部分字符有特殊含义,不代表字面的意思。它们叫做
    “元字符”(metacharacters)

(1)点字符(.)

  • 点字符(.)匹配除回车(\r)换行(\n)行分隔符(\u2028)段分隔符(\u2029)以外的所有字符。

(2)位置字符(^ $)

  • 位置字符用来提示字符所处的位置,主要有两个字符。
  • ^ 表示字符串的开始位置
  • $ 表示字符串的结束位置

(3)选择符(|)

  • 竖线符号(|)在正则表达式中表示“或关系”(OR)
  • 即cat|dog表示匹配cat或dog。
  • 多个选择符可以联合使用
  • 选择符会包括它前后的多个字符,比如/ab|cd/指的是匹配ab或者cd,而不是指匹配b或者c。如果想修改这个行为,可以使用圆括号。

// 匹配fred、barney、betty之中的一个

/fred|barney|betty/


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


/a( |\t)b/.test('a\tb')  -----------------true   a和b之间有一个空格或者一个制表符。

转义符 ( \ )

  • 正则表达式中那些有特殊含义的元字符,如果要匹配它们本身,就需要在它们前面要加上反斜杠,进行转义。
  • 正则表达式中,需要反斜杠转义的,一共有12个字符
  • ^.[$()|*+?{\\

正则表达式中,需要加反斜杠转义的,一共有12个字符:

^   $   .   |    (    )     [    {    ?  *   +    \\


点字符( . )
位置字符( ^ $ )  
选择符( | )   
量词符( ? * + ) 
字符类( [ )   
重复类( { )
组匹配( ( ) )
双反斜杠 ( \\ )
  • 需要特别注意的是,如果使用RegExp方法生成正则对象,转义需要使用两个斜杠,因为字符串内部会先转义一次。
(new RegExp('1\+1')).test('1+1')
// false

(new RegExp('1\\+1')).test('1+1')
// true


上面代码中,RegExp作为构造函数,参数是一个字符串。

但是,在字符串内部,反斜杠也是转义字符,
所以它会先被反斜杠转义一次,然后再被正则表达式转义一次,因此需要两个反斜杠转义。

特殊字符

  • 正则表达式对一些不能打印的特殊字符,提供了表达方法。
\cX 表示Ctrl-[X],其中的X是A-Z之中任一个英文字母,用来匹配控制字符。
[\b] 匹配退格键(U+0008),不要与\b混淆。
\n 匹配换行键。   -------------------------------- new line
\r 匹配回车键。   -------------------------------- return 
\t 匹配制表符 tab(U+0009)。
\v 匹配垂直制表符(U+000B)。
\f 匹配换页符(U+000C)。
\0 匹配null字符(U+0000)。
\xhh 匹配一个以两位十六进制数(\x00-\xFF)表示的字符。
\uhhhh 匹配一个以四位十六进制数(\u0000-\uFFFF)表示的 Unicode 字符。

字符类 ( [ ] )

------ 表示一系列的字符可供选择,只要匹配其中一个就可以。
  • 字符类(class)表示有一系列字符可供选择,只要匹配其中一个就可以了。
  • 所有可供选择的字符都放在方括号内,比如[xyz] 表示x、y、z之中任选一个匹配。
  • 有两个字符在字符类中有特殊含义。

(1)脱字符(^)

  • 如果方括号内的第一个字符是[^],则表示除了字符类之中的字符,其他字符都可以匹配。
  • [^xyz]表示除了x、y、z之外都可以匹配。
  • 如果方括号内没有其他字符,即只有[^],就表示匹配一切字符,其中包括换行符。
  • 相比之下,点号作为元字符(.)是不包括换行符的。
  • 注意,脱字符只有在字符类的第一个位置才有特殊含义,否则就是字面含义。

(2)连字符(-)

  • 某些情况下,对于连续序列的字符,连字符(-)用来提供简写形式,表示字符的连续范围。
  • 比如:
  • [abc]可以写成[a-c]
  • [0123456789]可以写成[0-9]
  • 同理[A-Z]表示26个大写字母
/a-z/.test('b') // false

/[a-z]/.test('b') // true


上面代码中,当连字号(dash)不出现在方括号之中,就不具备简写的作用,只代表字面的含义,所以不匹配字符b。

只有当连字号用在方括号之中,才表示连续的字符序列。
[0-9.,]
[0-9a-fA-F]
[a-zA-Z0-9-]
[1-31]
这些都是合法的字符类简写形式


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



[1-31]   ----------------------------------- 不代表1到31,只代表1到3。
/([12][0-9])|(3[01])/   -------------------- 表示1到31
  • 另外,不要过分使用连字符,设定一个很大的范围,否则很可能选中意料之外的字符。最典型的例子就是[A-z],表面上它是选中从大写的A到小写的z之间52个字母,但是由于在 ASCII 编码之中,大写字母与小写字母之间还有其他字符,结果就会出现意料之外的结果。

预定义模式

\d 匹配0-9之间的任一数字,相当于[0-9]。                     --------------------- digit 数字

\D 匹配所有0-9以外的字符,相当于[^0-9]。

\w 匹配任意的字母、数字和下划线,相当于[A-Za-z0-9_]。

\W 除所有字母、数字和下划线以外的字符,相当于[^A-Za-z0-9_]。

\s 匹配空格(包括换行符、制表符、空格符等),相等于[ \t\r\n\v\f]。

\S 匹配非空格的字符,相当于[^ \t\r\n\v\f]。

\b 匹配词的边界。                                          --------------------- boundary 边界

\B 匹配非词边界,即在词的内部。
  • [\S\s]指代一切字符。

重复类

  • 模式的精确匹配次数,使用大括号({})表示。
  • {n}表示恰好重复n次,
  • {n,}表示至少重复n次,
  • {n,m}表示重复不少于n次,不多于m次。

量词符


? 问号表示某个模式出现0次或1次,等同于{0, 1}。

* 星号表示某个模式出现0次或多次,等同于{0,}。

+ 加号表示某个模式出现1次或多次,等同于{1,}。

贪婪模式 ---------------- 3个量词符是贪婪模式

三个量词符,默认情况下都是最大可能匹配,即匹配直到下一个字符不满足匹配规则为止。这被称为贪婪模式。

  • 如果想将贪婪模式改为非贪婪模式,可以在量词符后面加一个问号。!!!!!!!!!!!!!!!!
var a = 'aaaaa';

var b = a.match(/a+/);
console.log(b);     ------------------------------- ["aaaaa", index: 0, input: "aaaaa"]

var c = a.match(/a*/);
console.log(c)      ------------------------------- ["aaaaa", index: 0, input: "aaaaa"]

3个量词符的匹配   默认是贪婪模式



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



要将贪婪模式转化为   非贪婪模式,就要在量词符后面加一个问号
----> 量词符后面加问号 ----> 转化成非贪婪模式

var a = 'aaaaa';

var b = a.match(/a+?/);  ------------------------------ ["a", index: 0, input: "aaaaa"]
console.log(b);

var c = a.match(/a*?/);  ------------------------------ ["", index: 0, input: "aaaaa"]
console.log(c)

  • 除了非贪婪模式的加号,还有非贪婪模式的星号(*)
    *?:表示某个模式出现0次或多次,匹配时采用非贪婪模式。
    +?:表示某个模式出现1次或多次,匹配时采用非贪婪模式。

修饰符

修饰符(modifier)表示模式的附加规则,放在正则模式的最尾部。

  • modifier:修饰符的意思
  • 修饰符可以单个使用,也可以多个一起使用。

(1)g 修饰符 ---------- global

  • 默认情况下,第一次匹配成功后,正则对象就停止向下匹配了。g修饰符表示全局匹配(global),加上它以后,正则对象将匹配全部符合条件的结果,主要用于搜索和替换。
var regex = /b/;
var str = 'abba';

regex.test(str); // true   ------------------------------------- 不加g,正则每次都从头开始匹配
regex.test(str); // true
regex.test(str); // true

上面代码中,正则模式不含g修饰符,每次都是从字符串头部开始匹配。
所以,连续做了三次匹配,都返回true。



-----------



var regex = /b/g;
var str = 'abba';

regex.test(str); // true
regex.test(str); // true
regex.test(str); // false

上面代码中,正则模式含有g修饰符,每次都是从上一次匹配成功处,开始向后匹配。

因为字符串abba只有两个b,所以前两次匹配结果为true,第三次匹配结果为false。

(2)i 修饰符

  • 默认情况下,正则对象区分字母的大小写,加上i修饰符以后表示忽略大小写(ignorecase)

(3)m 修饰符 ---- multiline多行模式,匹配换行符 \n

  • m修饰符表示多行模式(multiline),会修改^和$的行为。
  • 默认情况下(即不加m修饰符时),^$匹配字符串的开始处和结尾处,
  • 加上m修饰符以后,^$还会匹配行首和行尾,即^和$会识别换行符(\n)。
/world$/.test('hello world\n') // false
/world$/m.test('hello world\n') // true


/^b/m.test('a\nb') // true

------------------ a\nb   换行了,加了m,b就是在行首

上面代码要求匹配行首的b,如果不加m修饰符,就相当于b只能处在字符串的开始处。

加上b修饰符以后,换行符\n也会被认为是一行的开始。

组匹配

  • 正则表达式的括号表示分组匹配,括号中的模式可以用来匹配分组的内容。
/fred+/.test('fredd') // true
/(fred)+/.test('fredfred') // true
  • 注意,使用组匹配时,不宜同时使用g修饰符,否则match方法不会捕获分组的内容。
var m = 'abcabc'.match(/(.)b(.)/g);
m // ['abc', 'abc'] 

组匹配时,不宜使用g修饰符,上面情况就匹配了整个正则,而没有匹配组
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,937评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,503评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,712评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,668评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,677评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,601评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,975评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,637评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,881评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,621评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,710评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,387评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,971评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,947评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,189评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,805评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,449评论 2 342