美文网首页
看完必会的正则表达式和递归

看完必会的正则表达式和递归

作者: 小王子__ | 来源:发表于2021-12-11 02:00 被阅读0次

    1,递归

    递归函数:一个函数在内部可以调用其本身

    function func() {
      func()
    }
    func()
    
    image
    递归容易发生栈溢出错误(stack overflow),以上是一个典型的栈溢出,所以我们必须加退出条件 return
    var num = 1
    function func() {
      console.log(`打印${num}次`)
      if (num === 10) {
        return
      }
      num++
      func()
    }
    func()
    

    递归实例:

    • 1, 利用递归求 1 ~ n 的阶乘
    function func(n) {
      // 1 * 2 * 3 * ...n
      if (n === 1) return 1;
      return n * func(n - 1)
    }
    func(5)  // 120
    
    • 2, // 斐波那契数列(兔子序列):前两项的和等于第三项的值 表现: 1、1、2、3、5、8、13、21、34...
    // 用户输入一个数字 n, 求出这个数字对应的兔子序列值
    function fb (n) {
      if (n === 1 || n === 2) return 1
      return fb(n - 1) + fb(n - 2)
    }
    fb(9)  // 34
    
    • 3, 根据 id 返回对应的数据对象
    const arr = [
      {
        id: 1,
        name: 'Jerry',
        friends: [
          {
            id: 11,
            name: 'Lise'
          },
          {
            id: 12,
            name: 'Tom'
          }
        ]
      },
      {
        id: 2,
        name: 'xiaowang'
      }
    ];
    
    const arr = [
      {
        id: 1,
        name: 'Jerry',
        friends: [
          {
            id: 11,
            name: 'Lise'
          },
          {
            id: 12,
            name: 'Tom'
          }
        ]
      },
      {
        id: 2,
        name: 'xiaowang'
      }
    ];
    function getId(data, id) {
      var o = {}
      data.forEach(function (value) {
        if (value.id === id) {
          o = value
          return value
        } else if (value.friends?.length > 0) {
          o = getId(value.friends, id)
        }
      })
      return o
    }
    console.log(getId(arr, 12)) // {id: 12, name: 'Tom'}
    或者
    function getId(arr, id) {
      let queue = [];
      arr.forEach(item => {
        queue.push(item)
      })
      while(queue.length > 0) {
        const value = queue.shift();
        if(value.id === id) return value;
        if(value.friends && value.friends.length > 0) {
          value.friends.forEach(item => queue.push(item));
        }
      }
    }
    console.log(getId(arr, 12)) // {id: 12, name: 'Tom'}
    

    2,深浅拷贝

    • 1,浅拷贝只是拷贝一层,更深层对象级别的只拷贝引用
    • 2,深拷贝拷贝多层,每一级别的数据都会拷贝

    浅拷贝

    const obj = {
      name: 'Jerry',
      age: 18,
      friends: {
        name: 'Lise'
      }
    };
    var o = {}
    
    for (var i in obj) { // i 属性名,obj[i] 属性值
      o[i] = obj[i]
    }
    或
    Object.assign(o, obj)  // ES6新增的方法可以实现浅拷贝
    
    o.friends.name = 'Tom'
    console.log(o) 
    console.log(obj)
    
    image
    image

    深拷贝

    const obj = {
      name: 'Jerry',
      age: 18,
      friends: {
        name: 'Lise'
      },
      colors: ['red', 'green', 'blue']
    };
    var o = {}
    // 封装函数
    function deepCopy(newObj, oldObj) {
      for(var i in oldObj) {
        // 判断属性值是简单数据类型还是复杂数据类型
          // 1,获取属性值 oldObj[i]
          const item = oldObj[i]
          // 2, 判断这个值是否是数组
          if (item instanceof Array) {
            newObj[i] = []
            deepCopy(newObj[i], item)
          } else if (item instanceof Object) {
            // 3,判断这个值是否是对象
            newObj[i] = {}
            deepCopy(newObj[i], item)
          } else {
            // 4,属于基本数据类型
            newObj[i] = item
          }
      }
    }
    deepCopy(o, obj)
    
    image

    3,正则表达式

    正则表达式:用于匹配字符串中字符组合的模式,在JS中,正则表达式也是对象。

    通常用于检测、替换那些符合某个模式的文本,例如验证表单:用户名表单只能输入英文字母、数字或者下划线。

    还常用于过滤页面内容中的一些敏感词(替换),或者从字符串中获取我们想要的特定部分等

    3.1,创建正则表达式

    • 创建正则表达式:
      • 1, 利用 RegExp 对象来创建
      const rg = new RegExp(/表达式/)
      
      • 2, 利用字面量创建正则表达式
      const rg = /表达式/
      
    • 测试正则表达式 test
      test()正则对象的方法,用于检测字符串是否符合该规范,该对象会返回 truefalse
    const rg =  /123/
    rg.test(123) // true
    rg.test(456) // false
    
    • 正则的组成
      一个正则可以由简单的字符组成,比如/abc/,也可以是简单和特殊字符的组合,比如/ab*c/,特殊字符有叫元字符,在正则中具有特殊意义的专用符号,比如: ^、$、+等

    特殊符号可以参考:MDN正则表达式

    正则测试工具:https://tool.oschina.net/regex

    3.2,正则中的特殊字符

    • 3.2.1 边界符
      正则中的边界符(位置符)用来提示字符串所处的位置,主要有两个:^、$
      • ^ 匹配行首的文本
      • $ 匹配行尾的文本
    const rg =  /abc/ // /abc/表示只要包含有abc这个字符串返回的都是true
    console.log(rg.test('abc')) // true 
    console.log(rg.test('abcd')) // true
    console.log(rg.test('aabc')) // true
    
    const reg = /^abc/ // 表示必须以abc开头的
    console.log(reg.test('abc')) // true 
    console.log(reg.test('abcd')) // true
    console.log(reg.test('aabc')) // false
    console.log(reg.test('abdc')) // false
    
    const reg1 = /^abc$/ // 精确匹配
    console.log(reg1.test('abc')) // true 
    console.log(reg1.test('abcd')) // false
    console.log(reg1.test('aabc')) // false
    
    • 3.2.2 字符类:[]
      表示有一系列字符可供选择,只要匹配其中一个就可以了
    const reg = /[abc]/  // 表示只要包含有a 或 有b 或 有c,都返回true
    console.log(reg.test('alia')) // true
    
    const reg1 = /^[abc]$/  // 表示只有是a 或 b 或 c,才返回true
    console.log(reg1.test('alia')) // false
    console.log(reg1.test('a')) // true
    console.log(reg1.test('b')) // true
    console.log(reg1.test('bc')) // false
    console.log(reg1.test('c')) // true
    console.log(reg1.test('cc')) // false
    console.log(reg1.test('abc')) // false
    
    • 3.3.3 [-]方括号内 范围符 -
    const reg = /^[a-z]$/ // 26个英文字母任何一个字母返回true
    console.log(reg.test('alia')) // false
    console.log(reg.test('a')) // true
    console.log(reg.test('A')) // false
    
    • 3.3.4 字符组合
    // 字符组合
    const reg1 = /^[a-zA-Z]$/ // // 26个英文字母(大小写都可以) 任何 一个字母返回true
    console.log(reg1.test('alia')) // false
    console.log(reg1.test('a')) // true
    console.log(reg1.test('A')) // true
    
    // 比如:reg = /^[a-zA-Z0-9_-]$/
    
    • 3.4.5 []方括号内 表示取反
    const reg = /^[^abc]$/
    console.log(reg.test('a'))  // false
    
    • 3.4.6 量词符

    用来设定某个模式出现的次数

    量词 说明
    * 重复0次或更多次
    + 重复1次或更多次
    ? 重复0次或1次
    {n} 重复n次
    {n,} 重复n次或更多次
    {n,m} 重复n到m次
    // *  >= 0
    const reg = /^a*$/
    console.log(reg.test('')) // true
    console.log(reg.test('a')) // true
    console.log(reg.test('b')) // false
    console.log(reg.test('aaa')) // true
    
    // + >= 1
    const reg1 = /^a+$/
    console.log(reg1.test('')) // false
    console.log(reg1.test('a')) // true
    console.log(reg1.test('b')) // false
    console.log(reg1.test('aaa')) // true
    
    // ? 1 || 0
    const reg2 = /^a?$/
    console.log(reg2.test('')) // true
    console.log(reg2.test('a')) // true
    console.log(reg2.test('b')) // false
    console.log(reg2.test('aaa')) // false
    
    // {3} 重复3次
    const reg3 = /^a{3}$/
    console.log(reg3.test('')) // false
    console.log(reg3.test('a')) // false
    console.log(reg3.test('b')) // false
    console.log(reg3.test('aaa')) // true
    
    // {3,} >= 3
    const reg4 = /^a{3,}$/
    console.log(reg4.test('')) // false
    console.log(reg4.test('a')) // false
    console.log(reg4.test('b')) // false
    console.log(reg4.test('aaa')) // true
    console.log(reg4.test('aaaaa')) // true
    console.log(reg4.test('aaabc')) // false
    console.log('-----------')
    // {3,8}  >= 3 && <= 8
    const reg5 = /^a{3,8}$/
    console.log(reg5.test('')) // false
    console.log(reg5.test('a')) // false
    console.log(reg5.test('b')) // false
    console.log(reg5.test('aaa')) // true
    console.log(reg5.test('aaaaa')) // true
    console.log(reg5.test('aaabc')) // false
    console.log(reg5.test('aaaaaaaa')) // true
    
    • 3.4.7
    // 量词是设定某个模式出现的次数
    var reg = /^[a-zA-Z0-9_-]$/ // 这个模式用户只能输入英文字母 数字 下划线 短横线但是有边界符和[] 这就限定了只能多选1
    console.log(reg.test('a')) // true
    console.log(reg.test('ab')) // false
    console.log(reg.test(1)) // true
    console.log(reg.test('11')) // false
    console.log(reg.test('aa')) // false
    

    4, 正则案例

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

    const name = document.querySelector('.name');
    const span = document.querySelector('span');
    var reg = /^[a-zA-Z0-9_-]{6,16}$/
    name.onblur = function () {
      if (reg.test(this.value)) {
        span.className = 'green'
        span.innerHTML = '用户名合法'
      } else {
        span.className = 'red'
        span.innerHTML = '用户名不符合规范'
      }
    }
    

    5, 括号总结

    • 1,量词符大括号,表示重复次数
    • 2,字符集合中括号,匹配方括号中的任意字符
    • 3,小括号,表示优先级
    // 中括号[],字符集合,匹配方括号中的任意字符
    const reg = /^[abc]$/ // a || b || c都可以
    
    // 大括号{},量词符,表示重复次数
    const reg1 = /^[abc]{3}$/
    console.log(reg1.test('aaa')) // true
    console.log(reg1.test('abcabcabc')) // false
    
    const reg2 = /^abc{3}$/  // 它只是让c重复3次 abccc
    console.log(reg2.test('aaa')) // false
    console.log(reg2.test('abcabcabc')) // false
    console.log(reg2.test('bbb')) // false
    console.log(reg2.test('ccc')) // false
    console.log(reg2.test('abccc')) // true
    console.log(reg2.test('aabccc')) // false
    
    // 小括号 表示优先级
    const reg3 = /^(abc){3}$/ // 表示让 abc重复3次 
    console.log(reg3.test('aaa')) // false
    console.log(reg3.test('abcabcabc')) // true
    console.log(reg3.test('abccc')) // false
    

    6,可以在线测试自己写的正则对不对(https://c.runoob.com/front-end/854/)

    也会有一些常用的正则:


    image

    7,预定义类

    指的是某些常见模式的简写方式

    预定义类 说明
    \d 匹配0-9之间的任一数字, 相当于[0-9]
    \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]

    实例:

    //  座机号码验证:全国座机号码,两种格式:010-12345678 或者 0530-1234567
    // const reg = /^\d{3}-\d{8}|\d{4}-\d{7}$/  // 正则里的 或 用 | 表示
    // 简写
    const reg = /^\d{3,4}-\d{7,8}$/
    console.log(reg.test('魑魅魍魉')) // false
    console.log(reg.test('3829889')) // false
    console.log(reg.test('3829-889')) // false
    console.log(reg.test('022-31231321')) // true
    

    8, replace 替换

    replace()方法可以实现替换字符串操作,用来替换的参数可以是一个字符串或是一个正则

    // 语法
    str.replace(/str/, replacement)
    // 第一个参数:被替换的字符串 或者 正则
    // 第二个参数:替换为的字符串
    // 返回值是一个替换完的新字符串
    
    const str = 'JerryLise'
    const newStr = str.replace('Jerry', 'xiaowang')
    const newStr = str.replace(/Jerry/, 'xiaowang')
    console.log(newStr)  // xiaowangLise
    

    实例:

    const text = document.querySelector('textarea')
    const btn = document.querySelector('button')
    const div = document.querySelector('div')
    btn.onclick = function () {
        div.innerHTML = text.value.replace(/小猫咪/, '**')
    }
    
    image

    以上代码replace只能替换第一个满足条件的字符串,后面的就不再替换了,那么我们可以用正则表达式参数

    9,正则表达式参数

    /表达式/[switch]
    // switch也称修饰符,按照什么样的模式来匹配,有三种值:
    // 1,g: 全局匹配
    // 2,i:忽略大小写
    // 3,gi:全局匹配 + 忽略大小写
    

    以上实例:

    div.innerHTML = text.value.replace(/小猫咪|超/g, '**')
    
    image

    相关文章

      网友评论

          本文标题:看完必会的正则表达式和递归

          本文链接:https://www.haomeiwen.com/subject/skzhfrtx.html