《JavaScript正则表达式迷你书》读书笔记

正则基础

常见简写形式

字符组 具体含义 记忆方式
\d 表示 [0-9]。表示是一位数字。 其英文是 digit(数字)
\D 表示 [^0-9]。表示除数字外的任意字符。
\w 表示 [0-9a-zA-Z_]。表示数字、大小写字母和下划线。 w 是 word 的简写,也称单词字符。
\W 表示 [^0-9a-zA-Z_]。非单词字符。
\s 表示 [ \t\v\n\r\f]。表示空白符,包括空格、水平制表符、垂直制表符、换行符、回车符、换页 符。 s 是 space 的首字母,空白符的单词是 white space。
\S 表示 [^ \t\v\n\r\f]。 非空白符。
. 表示 [^\n\r\u2028\u2029]。通配符,表示几乎任意字符。换行符、回车符、行分隔符和段分隔符 除外。 想想省略号 ... 中的每个点,都可以理解成占位符,表示任何类似的东西。
[\d\D]/[\w\W]/[\s\S]/[^] 任意字符

量词

字符组 具体含义 记忆方式
{m, } 至少出现m次
{m} 等价于{m, m}, 出现m次
? 等价于{0, 1}, 出现或者不出现 问号的意思: 有么?
+ 等价于{1, }, 表示至少出现一次 加号是追加的意思,表示必须现有一个,然后才考虑追加
* 等价于{0, }, 出现任意次, 有可能不出现 看看天上的星星,可能一颗没有,可能零散有几颗,可能数也数不过来

修饰符

字符组 具体含义 记忆方式
g 匹配全局 单词是global
i 忽略字母大小写 单词是ignoreCase
m 多行匹配, 只影响 ^ 和 $,二者变成行的概念,即行开头和行结尾 单词是multiline

匹配位置

字符组 具体含义 记忆方式
^ (脱字符)匹配开头
$ (美元符号)匹配结尾
\b 单词边界 \w 与 \W 之间的位置,也包括 \w 与 ^ 之间的位置,和 \w 与 $ 之间的位置
\B 非单词边界
(?=p) "p"的子模式, "p" 前面的位置 positive lookahead(正向先行断言)
(?!p) 非"p"前的位置 negative lookahead(负向先行断言)

匹配开头与结尾

  • /^|$/g: 匹配列
  • /^|$/gm: 匹配行, m是既有修饰符

ES5之后版本支持的位置判断

  • (?<=p): positive lookbehind(正向后行断言)
  • (?: negative lookbehind(负向后行断言)

举例

  • 千分位
    • 千分位示例1234567890
      • 三位数字的前面: /(?=\d{3}$)/g
        • (?=p): 正向先行断言
      • 多个三位数字: /(?=(\d{3})+$)/g
        • +: 量词, 多个
      • 最前面不匹配: /(?!^)(?=(\d{3})+$)/g
        • (?!^): 负向先行断言
      • 非捕获:
        • 正则: /\B(?=(?:\d{3})+(?!\d))/g
          • 千位分隔符的理解
    • 带空格的千分位123456789 123456789
      • /(?!\b)(?=(\d{3})+\b)/g,即/(\B)(?=(\d{3})+\b)/g
      • ^$要替换成\b
    • 格式化千分位
      function format (num) {
        return num.toFixed(2).replace(/\B(?=(\d{3})+\b)/g, ",").replace(/^/, "$$ ");
      };
      console.log( format(1888) );
      // => "$ 1,888.00"
      
  • 验证密码: 长度为6~12位, 由数字、大写字母和小写字母,必须至少包含两种字符
    • 长度为6~12位的数字、大小写字母: /^[0-9a-zA-Z]{6, 12}$/
    • 至少包含两种
      • 解题核心
        • 至少包含一位数字字符: /(?=.*[0-9])/
      • 划分情况
        • 包含数字和大写字母
        • 包含数字和小写字母
        • 包含大写字母和小写字母
        • 包含数字、大写字母和小写字母
      • 正则: /((?=.*[0-9])(?=.*[a-z])|(?=.*[0-9])(?=.*[A-Z])|(?=.*[a-z])(?=.*[A-Z]))^[0-9a-zA-Z]{6,12}$/
        • 注意: {6,12}中间不能有空格
    • 不能同时全部为一种(反向思路)
      • 解题核心
        • 不能全部为一种字符(数字): /(?!^[0-9]{6,12}$)(^[0-9a-zA-Z]{6,12})/
      • 划分情况
        • 不能全为数字
        • 不能全为大写字母
        • 不能全为小写字母
      • 正则: /(?!^[0-9]{6,12}$)(?!^[a-z]{6,12}$)(?!^[A-Z]{6,12}$)(^[0-9a-zA-Z]{6,12}$)/

常用正则

词法 含义 记忆方式
(?=.[A-Z]) / (?=.?[A-Z]) / (.*[A-Z]) 至少包含一个大写字母

括号的作用

分组和分支

  • 分组: 'ababa abbb ababab'.match(/(ab)+/g)
  • 分支: (p1|p2)
    • 示例
      var regex = /^I love (JavaScript|Regular Expression)$/
      console.log(regex.test("I love JavaScript")) // true
      console.log(regex.test("I love Regular Expression")) // true
      

分组引用: 正则引擎给分组开辟了一个空间, 用来存储每个分组匹配到的数据

  • 分组方法
    • 之前: /^d{4}-d{2}-d{2}$/
    • 之后: /^(d{4})-(d{2})-(d{2})$/
  • 提取数据:
    • match方法
      • 使用: '2017-06-12'.match(/(\d{4})-(\d{2})-(\d{2})/)
      • match返回数组: ["2017-06-12", "2017", "06", "12", index: 0, input: "2017-06-12", groups: undefined]
        • 第一个是整体匹配结果
        • 然后是各个分组匹配到的结果
        • 匹配下标
        • 输入的文本
        • 一个捕获组数组 或 undefined(如果没有定义命名捕获组)
      • 注意:
        • 使用g之后, 返回的是一个数组
          • 举例: '1s1'.match(/\d/g) => ["1", "1"]
        • 匹配不到, 则返回null
    • exec方法
      • 使用: /(\d{4})-(\d{2})-(\d{2})/.exec('2017-06-12')
    • 正常操作(test/match/exec)之后, 可以通过RegExp$0~$9获取
  • 替换: 转换yyyy-mm-dddd/mm/yyyy
    • $方法
      '2019-09-23'.replace(/(\d{4})-(\d{2})-(\d{2})/, '$2/$3/$1')
      
    • RegExp.$+function方法
      '2019-09-23'.replace(/(\d{4})-(\d{2})-(\d{2})/, function() {
          return `${RegExp.$2}/${RegExp.$3}/${RegExp.$1}`
      })
      
    • function方法
      '2019-09-23'.replace(/(\d{4})-(\d{2})-(\d{2})/, function(match, year, month, day) {
          return `${month}/${day}/${year}`
      })
      

反向引用: \1

  • 同时匹配日期格式: 2019-09-24, 2019/09/24, 2019.09.24
    • 正则: /\d{4}(-|\/|\.)\d{2}(-|\/|\.)\d{2}/
    • 问题: 格式不统一, 2019/09-24同样能匹配
    • 解决方法: 使用反向引用
      • 正则: /\d{4}(-|\/|\.)\d{2}(\1)\d{2}/
    • 同理: \2是第二个分组引用, 依次类推
  • 括号嵌套
    • 正则
      // ["1231231233", "123", "1", "23", "3", index: 0, input: "1231231233", groups: undefined]
      1231231233'.match(/^((\d)(\d(\d)))\1\2\3\4$/) 
      
    • 拆分
      • /^((\d)(\d(\d)))$/.test('123') // true
      • /^(\d)$/.test('1') // true
      • /^(\d(\d))$/.test('23') // true
      • /^(\d)$/.test('3') // true, 同第二个一样
  • 引用不存在的分组
    • 会匹配反向引用本身
      • 正则: /\1/.test('\1') // true
  • 分组后由量词
    • 会匹配到最后一次匹配
      • 正则: '12345'.match(/(\d)+/) // ["12345", "5", index: 0, input: "12345", groups: undefined]
      • 对于反向引用, 同理: /(\d)+ \1/.test('12345 5') // true

非捕获括号: (?:p)

非捕获匹配到的值不会保存起来

  • 与之相反的是
    • 捕获型分组
    • 捕获型分支
  • 举例
    'ababa abbb ababab'.match(/(?:ab)+/g) // ["abab", "ab", "ababab"]
    var regex = /^I love (?:JavaScript|Regular Expression)$/
    regex.test("I love JavaScript") // true
    regex.test("I love Regular Expression") // true
            ```
    

实战应用

trim: 去掉头部和尾部的空字符串

  • js: ' hello '.trim() // 'hello'
  • 正则:
    • 匹配到开头和结尾的空字符串, 替换掉(效率高)
      '  hello '.replace(/^\s+|\s+$/g, '')
      
    • 惰性匹配*?, 匹配所有字符串, 提取相应数据
      '  hello '.replace(/^\s*(.*?)\s*$/, '$1') // 'hello'
      

将每个单词的首字母转换为大写

  • 方法
    function titleize (str) {
        return str.toLowerCase().replace(/(?:^|\s)\w/g, function (c) {
            return c.toUpperCase();
        });
    }
    // My Name Is Epeli
    console.log( titleize('my name is epeli') )
    
  • 注意
    • \s: 制表符空格等, 用来匹配name这样的数据

驼峰

  • 方法
    var camelize = function(str) {
        return str.replace(/[-_\s]+(.)?/g, function(match, c){
            return c ? c.toUpperCase() : ''
        })
    }
    console.log(camelize('-moz-transform'))
    
  • 注意
    • replace: 关于replace参数
      • match: 匹配到的字符串
      • p1,p2,...: 代表第n个括号匹配到的字符串
      • offset: 匹配到字符串在原字符串的偏移量
      • string: 被匹配的原字符串
      • NamedCaptureGroup: 命名捕获组匹配的对象
    • [-_\s]: 连字符、下划线和空白符
    • ?: 应对单词结尾不是单词字符, 例如'-moz-transform '

中划线化

  • 方法
    var dasherize = function(str) {
        return str.replace(/([A-Z])/g, '-$1').replace(/[-_\s]+/g, '-').toLowerCase()
    }
    console.log(dasherize('MozTTransform'))
    
  • 或者使用function
    var sperateLine = function(str) {
        return str.replace(/[A-Z]{1}/g, function(match) {
            return match ? `-${match.toLowerCase()}` : ''
        })
    }
    console.log(sperateLine('MozTTransform'))
    

HTML转义和反转义

  • 转义
    • 方法
      var escapeHTML = function(str) {
          var escapeChars = {
              '<': 'lt',
              '>': 'gt',
              '"': 'quot',
              '&': 'amp',
              '\'': '#39'
          }
          return str.replace(new RegExp(`[${Object.keys(escapeChars).join('')}]`, 'g'), function(match) {
              return `&${escapeChars[match]};`
          })
      }
      console.log(escapeHTML('
      hello, \'world\'
      '))
  • 反转义
    • 方法
      var unescapeHTML = function(str) {
          var htmlEntities = {
              'lt': '<',
              'gt': '>',
              'quot': '"',
              'amp': '&',
              '#39': '\''
          }
          return str.replace(new RegExp(`\&([^;]+);`, 'g'), function(match, key) {
              console.log(match, key)
              return (key in htmlEntities) ? htmlEntities[key] : match
          })
      }
      console.log(unescapeHTML('<div>hello, 'world'</div>'))
      
    • 注意
      • 关于/\&([^;]+);/g^
        • 匹配输入字符串开头位置
        • 方括号中使用, 表示不接受该字符集合
        • 匹配^本身,使用\^
        • 图示:
          image.png
  • 成对标签
    • 简单匹配正则: /<([^>]+)>[\d\D]*<\/\1>/
    • 验证: /<([^>]+)>[\d\D]*<\/\1>/.test('wrong!</p>') // false</code> </li> </ul> </li> </ul> <h3>回溯法</h3> <ul> <li>没有回溯的匹配 <ul> <li>举例: <code>/ab{1,3}c/.test('abbbc')</code> </li> </ul> </li> <li>有回溯的匹配 <ul> <li>举例: <code>/ab{1,3}c/.test('abbc')</code> </li> </ul> </li> <li>回溯产生的原因: 一次没有恰好匹配, 需要多次匹配</li> <li>建议: 应该避免 <ul> <li>举例 <pre><code>// .*任意字符出现任意次, 会匹配到abc"de, 匹配完之后发现还有"正则, 然后会回溯,只匹配到abc /".*"/.test('"abc"de') // 更改建议, 匹配非"的字符任意次, 碰到"就终止匹配, 减少回溯, 提高效率 /"[^"]*"/.test('"abc"de') </code></pre> </li> </ul> </li> <li>释义 <ul> <li> <p>百度百科</p> <blockquote> <p>回溯法也称试探法,它的基本思想是:从问题的某一种状态(初始状态)出发,搜索从这种状态出发 所能达到的所有“状态”,当一条路走到“尽头”的时候(不能再前进),再后退一步或若干步,从 另一种可能“状态”出发,继续搜索,直到所有的“路径”(状态)都试探过。这种不断“前进”、 不断“回溯”寻找解的方法,就称作“回溯法”。</p> </blockquote> </li> <li><p>本质: 深度优先搜索算法</p></li> <li><p>回溯: 退到之前的某一步的过程</p></li> </ul> </li> <li>常见的回溯形式 <ul> <li>贪婪量词 <ul> <li>尝试顺序从多往少的方向去尝试</li> <li>举例 <pre><code>// ["12345", "123", "45", index: 0, input: "12345", groups: undefined] '12345'.match(/(\d{1,3})(\d{1,3})/) </code></pre> </li> </ul> </li> <li>惰性量词 <ul> <li>贪婪量词后加问号尽可能少的匹配</li> <li>举例 <pre><code>// ["1234", "1", "234", index: 0, input: "12345", groups: undefined] '12345'.match(/(\d{1,3}?)(\d{1,3})/) </code></pre> </li> <li>会回溯的惰性 <pre><code>// ["12345", index: 0, input: "12345", groups: undefined] '12345'.match(/^\d{1,3}?\d{1,3}$/) </code></pre> </li> </ul> </li> <li>分支结构 <ul> <li>分支也是惰性匹配 <pre><code>// ["can", index: 0, input: "candy", groups: undefined] 'candy'.match(/can|candy/) </code></pre> </li> <li>整体匹配的话,也会回溯 <pre><code>// ["candy", index: 0, input: "candy", groups: undefined] 'candy'.match(/^(?:can|candy)$/) </code></pre> </li> </ul> </li> <li>总结 <ul> <li>回溯相对DFA引擎, 匹配效率低一些</li> <li>概念 <ul> <li>DFA: 确定型有限自动机</li> <li>NFA: 非确定型有限自动机 <ul> <li>JavaScript就是, 而且流行, 匹配慢(相对DFA)</li> <li>流行原因: 编译快, 有趣?</li> </ul> </li> </ul> </li> </ul> </li> </ul> </li> </ul> <h3>拆分</h3> <ul> <li> <p>结构的具体含义</p> <table> <thead> <tr> <th>结构</th> <th>说明</th> <th>举例</th> </tr> </thead> <tbody> <tr> <td>字面量</td> <td>匹配一个具体字符,包含需要转义和不需要转义的</td> <td>不转义: <code>/a/</code>匹配字符<code>'a'</code>; 转义: <code>/\n/</code>匹配换行符, <code>\.</code>匹配小数点</td> </tr> <tr> <td>字符组</td> <td>匹配一个字符,可以是多种可能之一;反义字符组,表示除特定字符的其他字符</td> <td> <code>/[0-9]/</code>表示匹配一个数字, 简写形式<code>/\d/</code>; <code>[^0-9]</code>表示匹配一个非数字, 简写形式<code>/\D/</code> </td> </tr> <tr> <td>量词</td> <td>表示一个字符连续出现; 或常见的简写形式</td> <td> <code>/a{1,3}/</code>表示<code>a</code>字符连续出现1~3次; <code>/a+/</code>表示<code>a</code>出现至少一次</td> </tr> <tr> <td>锚</td> <td>匹配一个位置, 而不是字符</td> <td> <code>^</code>表示匹配位置的开头, <code>\b</code>表示匹配单词边界, <code>(?=\d)</code>表示数字的前面</td> </tr> <tr> <td>分组</td> <td>用括号表示一个整体</td> <td> <code>(ab)+</code>表示<code>ab</code>两个字符连续出现多次, 也可以使用非捕获组<code>(?:ab)+</code> </td> </tr> <tr> <td>分支</td> <td>多个子表达式多选一, 反向引用</td> <td>`abc</td> <td>bcd<code>表示匹配</code>'abc'<code>或者</code>'bcd'<code>字符子串;</code>\2`表示引用第2个分组</td> </tr> </tbody> </table> </li> <li> <p>操作符(从上至下)</p> <table> <thead> <tr> <th>操作符描述</th> <th>操作符</th> <th>优先级</th> </tr> </thead> <tbody> <tr> <td>转义符</td> <td><code>\</code></td> <td>1</td> </tr> <tr> <td>括号和方括号</td> <td> <code>(...)</code>、<code>(?:...)</code>、<code>(?=...)</code>、<code>(?!...)</code>、<code>[...]</code> </td> <td>2</td> </tr> <tr> <td>量词限定符</td> <td> <code>{m}</code>、<code>{m,n}</code>、<code>{m,}</code>、<code>?</code>、<code>*</code>、<code>+</code> </td> <td>3</td> </tr> <tr> <td>位置和序列</td> <td> <code>^</code>、<code>$</code>、<code>\元字符</code>、<code>一般字符</code> </td> <td>4</td> </tr> <tr> <td>管道符(竖杠)</td> <td>`</td> <td>`</td> <td>5</td> </tr> </tbody> </table> <ul> <li>举例: <code>/ab?(c|de*)+|fg/</code> </li> </ul> </li> <li> <p>注意</p> <ul> <li>匹配字符串整体问题 <ul> <li>错误示例: <code>/^abc|bcd$/</code><br> <div class="image-package"> <div class="image-container" style="max-width: 201px; max-height: 67px;"> <div class="image-view"> </div> </div> <div class="image-caption"> QQ20191010-145021.png </div> </div> </li> <li>正确示例: <code>/^(abc|bcd)$/</code><br> <div class="image-package"> <div class="image-container" style="max-width: 291px; max-height: 90px;"> <div class="image-view"> </div> </div> <div class="image-caption"> QQ20191010-145048.png </div> </div> </li> <li>原因: 位置操作符优先级高于管道操作符</li> </ul> </li> <li>量词连缀问题 <ul> <li>每个字符为<code>'a'</code>,<code>'b'</code>,<code>'c'</code>任选其一, 字符串长度是3的倍数 <ul> <li> <p>错误示例: <code>/^[abc]{3}+$/</code></p> <blockquote> <p>会报错, 说<code>+</code>前没有什么可重复的</p> </blockquote> </li> <li> <p>正确示例: <code>/([abc]{3})+/</code><br> </p> <div class="image-package"> <div class="image-container" style="max-width: 142px; max-height: 179px;"> <div class="image-view"> </div> </div> <div class="image-caption"> QQ20191010-150526.png </div> </div> <p></p> </li> </ul> </li> </ul> </li> <li>元字符转义问题 <ul> <li>元字符 <pre><code>/\^\$\.\*\+\?\|\\\/\[\]\{\}\=\!\:\-\,/.test('^$.*+?|\\/[]{}=!:-,') </code></pre> </li> <li>字符串中, 每个字符转义之后还是本身 <pre><code>// true '^$.*+?|\\/[]{}=!:-,' === '\^\$\.\*\+\?\|\\\/\[\]\{\}\=\!\:\-\,' </code></pre> <ul> <li>不是每个字符都需要转义 <ul> <li>跟字符组有关的<code>[</code>、<code>]</code>、 <code>^</code>、 <code>-</code>。因此在会引起歧义的地方进行转义, 例如<code>^</code>, 否则会把整个字符组看成反义字符组 <pre><code>'^$.*+?|\\/[]{}=!:-,'.match(/[\^$.*+?|\\/\[\]{}=!:\-,]/g) </code></pre> </li> <li>匹配<code>'[abc]'</code>和<code>{3,5}</code> <pre><code>/\[abc]/.test('[abc]') /\{3,5}/.test('{3,5}') /{,3}/.test('{,3}') </code></pre> <ul> <li>原因: <em>只需要在第一个方括号转义即可,因为后面的方括号构不成字符组,正则不会引发歧义,自然不需要转义</em> </li> </ul> </li> <li>其他 <ul> <li> <code>=</code>, <code>!</code>, <code>:</code>, <code>-</code>, <code>,</code>不在特殊结构, 不需要转义</li> <li>括号前后需要转义, <code>/\(123\)/</code> </li> <li> <code>^</code>, <code>$</code>, <code>.</code>, <code>*</code>, <code>+</code>, <code>?</code>, <code>|</code>, <code>\</code>, <code>/</code>等字符, 只要不在字符组内, 都需要转义</li> </ul> </li> </ul> </li> </ul> </li> </ul> </li> <li>案例分析 <ul> <li>正则: <code>/^(\d{15}|\d{17}[\dxX])$/</code> </li> <li>IPV4正则: <code>/^((0{0,2}\d|0?\d{2}|1\d{2}|2[0-4]\d|25[0-5])\.){3}(0{0,2}\d|0?\d{2}|1\d{2}|2[0-4]\d|25[0-5])$/</code> <ul> <li>结构: <code>((...)\.){3}(...)</code> </li> <li>结构匹配: <code>3位数.3位数.3位数.3位数</code> </li> <li>拆分 <ul> <li> <code>0{0,2}\d</code>: 匹配 <pre><code>0~9 // 或 00~09 // 或 000~009 </code></pre> </li> <li> <code>0?\d{2}</code>: 匹配 <pre><code>10~99 // 或 010~099 </code></pre> </li> <li> <code>1\d{2}</code>: 匹配<code>100</code>~<code>199</code> </li> <li> <code>2[0-4]\d</code>: 匹配<code>200</code>~<code>249</code> </li> <li> <code>25[0-5]</code>: 匹配<code>250</code>~<code>255</code> </li> </ul> </li> </ul> </li> </ul> </li> </ul> </li> </ul> <h3>正则表达式构建</h3> <ul> <li> <p>平衡法则</p> <ul> <li>匹配预期的字符串</li> <li>不匹配非预期的字符串</li> <li>可读性和可维护性</li> <li>效率</li> </ul> </li> <li> <p>构建正则前提</p> <ul> <li>是否能使用正则 <ul> <li>举例: <code>'1010010001...'</code> </li> </ul> </li> <li>是否有必要使用(复杂)正则 <ul> <li>字符串分隔举例 <pre><code>var string = '2017-07-01' // 正则 var reg = /^(\d{4})-(\d{2})-(\d{2})/ console.log(string.match(reg)) // js api var stringArray = string.split('-') console.log(stringArray) </code></pre> </li> <li>判断是否有问号 <pre><code>var string = '?id=xx&act=search' // 正则 console.log(string.search(/\?/)) // js api console.log(string.indexOf('?')) </code></pre> </li> <li>获取子串 <pre><code>var string = 'JavaScript' // 正则 var reg = /.{4}(.+)/ console.log(string.match(reg)[1]) // js api console.log(string.substring(4)) </code></pre> </li> <li>是否有必要构建一个复杂的正则 <ul> <li>密码问题: 长度6~12位, 由数字、小写和大写字符组成, 必须包含两种字符</li> <li>复杂正则: <code>/(?!^[0-9]{6,12}$)(?!^[a-z]{6,12}$)(?!^[A-Z]{6,12}$)^[0-9A-Za-z]{6,12}$/</code> </li> <li>分拆简单正则: <pre><code>var regex1 = /^[0-9a-zA-Z]{6,12}$/ var regex2 = /^[0-9]$/ var regex3 = /^[a-z]$/ var regex4 = /^[A-Z]$/ function checkPassword = function(string) { if (!regex1.test(string) return false if (regex2.test(string)) return false if (regex3.test(string)) return false if (regex4.test(string)) return false return true } </code></pre> </li> </ul> </li> </ul> </li> </ul> </li> <li> <p>准确性</p> <ul> <li>问题1: <ul> <li>描述:匹配如下格式固话<code>055188888888</code>、<code>0551-88888888</code>、<code>(0551)88888888</code> </li> <li>分析(不考虑分机号和<code>+86</code>) <ul> <li>区号, 以0开头的3~4位数字, 正则: <code>/0\d{2,3}/</code> </li> <li>号码, 非0开头的6~7位数字, 正则: <code>/[1-9]\d{6,7}/</code> </li> <li>匹配<code>055188888888</code>, 正则: <code>/^0\d{2,3}[1-9]\d{6,7}$/</code> </li> <li>匹配<code>0551-88888888</code>, 正则: <code>/^0\d{2,3}-[1-9]\d{6,7}$/</code> </li> <li>匹配<code>(0551)88888888</code>, 正则: <code>/^\(0\d{2,3}\)[1-9]\d{6,7}$/</code> </li> <li>合并正则: <code>^/0\d{2,3}[1-9]\d{6,7}|0\d{2,3}-[1-9]\d{6,7}|\(0\d{2,3}\)[1-9]\d{6,7}$/</code> </li> <li>提取公共正则: <code>/^(0\d{2,3}|0\d{2,3}-|\(0\d{2,3}\))[1-9]\d{6,7}$/</code> </li> <li>进一步简写: <code>/^(0\d{2,3}-?|\(0\d{2,3}\))[1-9]\d{6,7}$/</code><br> <div class="image-package"> <div class="image-container" style="max-width: 561px; max-height: 151px;"> <div class="image-view"> </div> </div> <div class="image-caption"> QQ20191011-121606.png </div> </div> </li> </ul> </li> <li>测试 <pre><code>/^(0\d{2,3}-?|\(0\d{2,3}\))[1-9]\d{6,7}$/.test('055188888888') /^(0\d{2,3}-?|\(0\d{2,3}\))[1-9]\d{6,7}$/.test('0551-88888888') /^(0\d{2,3}-?|\(0\d{2,3}\))[1-9]\d{6,7}$/.test('(0551)88888888') /^(0\d{2,3}-?|\(0\d{2,3}\))[1-9]\d{6,7}$/.test('051-8888888') </code></pre> </li> <li>问题 <ul> <li>3位和4位数字不一定是真实区号</li> </ul> </li> </ul> </li> <li>问题2: <ul> <li>描述: 匹配如下格式浮点数<code>1.23</code>、<code>+1.23</code>、<code>-1.23</code>、<code>10</code>、<code>+10</code>、<code>-10</code>、<code>.2</code>、<code>+.2</code>、<code>-.2</code> </li> <li>分析 <ul> <li>符号部分: <code>[+-]</code> </li> <li>整数部分: <code>\d+</code> </li> <li>小数部分: <code>\.\d+</code> </li> <li>匹配<code>1.23</code>、<code>+1.23</code>、<code>-1.23</code>正则: <code>/^[+-]?\d+\.\d+$/</code> </li> <li>匹配<code>10</code>、<code>+10</code>、<code>-10</code>正则: <code>/^[+-]?\d+$/</code> </li> <li>匹配<code>.2</code>、<code>+.2</code>、<code>-.2</code>正则: <code>/^[+-]?\.\d+$/</code> </li> <li>合并正则: <code>/^[+-]?(\d+\.\d+|\d+|\.\d+)$/</code><br> <div class="image-package"> <div class="image-container" style="max-width: 497px; max-height: 163px;"> <div class="image-view"> </div> </div> <div class="image-caption"> float_1.png </div> </div> </li> <li>另外一种写法: <code>/^[+-]?(\d+)?(\.)?\d+$/</code> <blockquote> <p>涉及到可维护性和可读性</p> </blockquote> </li> </ul> </li> </ul> </li> </ul> </li> <li> <p>效率</p> <ul> <li> <p>正则运行阶段</p> <ul> <li> <p>编译</p> <blockquote> <p>引擎报错与否在这个阶段</p> </blockquote> </li> <li><p>设定起始位置</p></li> <li> <p>尝试匹配</p> <blockquote> <p>可以优化的阶段</p> </blockquote> </li> <li> <p>匹配失败,从下一位开始继续第3步</p> <blockquote> <p>可以优化的阶段</p> </blockquote> </li> <li><p>最终结果: 匹配成功或失败</p></li> </ul> </li> <li> <p>运行代码示例</p> <pre><code>var regex = /\d+/g; // 0 ["123", index: 0, input: "123abc34def", groups: undefined] console.log( regex.lastIndex, regex.exec("123abc34def") ); // 3 ["34", index: 6, input: "123abc34def", groups: undefined] console.log( regex.lastIndex, regex.exec("123abc34def") ); // 8 null console.log( regex.lastIndex, regex.exec("123abc34def") ); // 0 ["123", index: 0, input: "123abc34def", groups: undefined] console.log( regex.lastIndex, regex.exec("123abc34def") ); </code></pre> <blockquote> <p>当使用<code>test</code>和<code>exec</code>时, 正则有<code>g</code>时, 起始位置是从<code>lastIndex</code>开始的</p> </blockquote> </li> <li> <p>优化方法</p> <ul> <li> <p>使用具体型字符组代替通配符, 来消除回溯</p> <ul> <li> <code>/".*"/.test('123"abc"456')</code>: 回溯有4次</li> <li> <code>/".*?"/.test('123"abc"456')</code>: 回溯有2次 <ul> <li>惰性匹配<code>*?</code> </li> </ul> </li> <li> <code>/"[^"]*"/.test('123"abc"456')</code>: 无回溯</li> </ul> </li> <li> <p>使用非捕获分组</p> <blockquote> <p>不需要使用分组引用和反向引用时</p> </blockquote> <ul> <li> <code>/^[+-]?(\d+\.\d+|\d+|\.\d+)$/</code>=><code>/^[+-]?(?:\d+\.\d+|\d+|\.\d+)$/</code> </li> </ul> </li> <li> <p>独立出确定字符</p> <ul> <li> <code>/a+/</code> => <code>/aa*/</code> </li> </ul> </li> <li> <p>提取公共分支部分</p> <blockquote> <p>可减少匹配过程中的重复</p> </blockquote> <ul> <li> <code>/^abc|^bcd/</code> => <code>/^(abc|bcd)/</code> </li> <li> <code>/this|that/</code> => <code>/th(?:is|at)/</code> </li> </ul> </li> <li> <p>减少分支的数量, 缩小它们范围</p> <ul> <li> <code>/red|read/</code> => <code>/rea?d/</code>: 可读性降低</li> </ul> </li> </ul> </li> <li> <p>总结</p> <ul> <li>关于准确性: 满足需求即可</li> <li>关于效率: 看个人要求</li> <li>准确性思路 <ul> <li>针对每种情形, 分别写出正则</li> <li>再用分支进行合并</li> <li>提取公共部分</li> </ul> </li> </ul> </li> </ul> </li> </ul> <h3>正则表达式编程</h3> <ul> <li><p>匹配: 目标字符串中是否有匹配的子串</p></li> <li> <p>正则表达式的四种操作</p> <ul> <li>验证: 判断是否的操作 <ul> <li> search <pre><code>// true !!~'abc123'.search(/\d/) </code></pre> </li> <li> match <pre><code>// true !!'abc123'.match(/\d/) </code></pre> </li> <li> test <pre><code>// true /\d/.test('abc123') </code></pre> </li> <li> exec <pre><code>// true !!/\d/.exec('abc123') </code></pre> </li> </ul> </li> <li>切分: <ul> <li>切分<code>,</code>分隔的字符串 <pre><code>// ["html", "js", "css"] 'html,js,css'.split(/,/) </code></pre> </li> <li>日期切割 <pre><code>// ["2019", "10", "11"] '2019/10/11'.split(/\D/) '2019.10.11'.split(/\D/) '2019-10-11'.split(/\D/) </code></pre> </li> </ul> </li> <li>提取: <ul> <li>search <pre><code>'2019-10-11'.search(/^(\d{4})\D(\d{2})\D(\d{2})$/) // 2019 10 11 console.log(RegExp.$1, RegExp.$2, RegExp.$3) </code></pre> </li> <li>match <pre><code>// ["2019-10-11", "2019", "10", "11", index: 0, input: "2019-10-11", groups: undefined] '2019-10-11'.match(/^(\d{4})\D(\d{2})\D(\d{2})$/) </code></pre> </li> <li> replace <pre><code>var date = [] '2019-10-11'.replace(/^(\d{4})\D(\d{2})\D(\d{2})$/, function(year, month, day) { date.push(year, month, day) }) // ["2019-10-11", "2019", "10"] console.log(date) </code></pre> </li> <li>test <pre><code>/^(\d{4})\D(\d{2})\D(\d{2})$/.test('2019-10-11') // 2019 10 11 console.log(RegExp.$1, RegExp.$2, RegExp.$3) </code></pre> </li> <li>exec <pre><code>/^(\d{4})\D(\d{2})\D(\d{2})$/.exec('2019-10-11') // 2019 10 11 console.log(RegExp.$1, RegExp.$2, RegExp.$3) </code></pre> </li> </ul> </li> <li> <em>替换</em>: 需要重点掌握 <pre><code>var tody = new Date('2019-10-11'.replace(/-/g, '/')) // Fri Oct 11 2019 00:00:00 GMT+0800 (China Standard Time) console.log(tody) </code></pre> </li> </ul> </li> <li> <p>相关API注意要点</p> <ul> <li> <p><code>search</code>和<code>match</code>会把字符串转成正则</p> <pre><code>// 0 '2019.10.11'.search('.') // ["2", index: 0, input: "2019.10.11", groups: undefined] '2019.10.11'.match('.') // 4 '2019.10.11'.search('\\.') // [".", index: 4, input: "2019.10.11", groups: undefined] '2019.10.11'.match('\\.') // 4 '2019.10.11'.search(/\./) // [".", index: 4, input: "2019.10.11", groups: undefined] '2019.10.11'.match(/\./) // "2019/10.11" '2019.10.11'.replace('.', '/') </code></pre> </li> <li> <p><code>match</code>返回的格式问题: 与是否有修饰符<code>g</code>有关</p> <pre><code>// ["2019", "2019", index: 0, input: "2019.10.11", groups: undefined] console.log('2019.10.11'.match(/\b(\d+)\b/)) // ["2019", "10", "11"] console.log('2019.10.11'.match(/\b(\d+)\b/g)) </code></pre> </li> <li> <p><code>exec</code>比<code>match</code>更强大: <code>match</code>使用<code>g</code>之后, 没有关键信息<code>index</code>, <code>exec</code>可以解决这个问题, 并且接着上一次继续匹配</p> <pre><code>var string = "2019.10.11"; var regex2 = /\b(\d+)\b/g; // ["2019", "2019", index: 0, input: "2019.10.11", groups: undefined] console.log( regex2.exec(string) ); // 4 console.log( regex2.lastIndex); // ["10", "10", index: 5, input: "2019.10.11", groups: undefined] console.log( regex2.exec(string) ); // 7 console.log( regex2.lastIndex); // ["11", "11", index: 8, input: "2019.10.11", groups: undefined] console.log( regex2.exec(string) ); // 10 console.log( regex2.lastIndex); // null console.log( regex2.exec(string) ); // 0 console.log( regex2.lastIndex); </code></pre> <ul> <li> <p>对使用<code>exec</code>用法优化</p> <blockquote> <p>示例中<code>lastIndex</code>表示下次匹配的开始位置</p> </blockquote> <pre><code>var string = '2019.10.11' var regex = /\b(\d+)\b/g var result while (result = regex.exec(string)) { console.log(result, regex.lastIndex) } </code></pre> </li> </ul> </li> <li> <p>修饰符<code>g</code>对<code>exec</code>和<code>test</code>的影响</p> <ul> <li>字符串的四个方法, 每次匹配都是从0开始, 即<code>lastIndex</code>属性始终不变 <pre><code>var regex = /a/g 'a'.search(regex) // 0 console.log(regex.lastIndex) 'ab'.search(regex) // 0 console.log(regex.lastIndex) </code></pre> </li> <li>正则的<code>exec</code>和<code>test</code>方法, 当正则含有<code>g</code>, 每次匹配都会更改<code>lastIndex</code>; 不含<code>g</code>, 则不会改变<code>lastIndex</code> <pre><code>var regex = /a/g // true 1 console.log( regex.test('a'), regex.lastIndex ) // true 3 console.log( regex.test('abac'), regex.lastIndex ) // false 0 console.log( regex.test('abacd'), regex.lastIndex ) </code></pre> </li> </ul> </li> <li> <p><code>test</code>整体匹配时需要<code>^</code>和<code>$</code></p> <blockquote> <p><code>test</code>是看目标字符串中是否有子串符合条件</p> </blockquote> <pre><code>// true /123/.test('a123b') // false /^123$/.test('a123b') // true /^123$/.test('123') </code></pre> </li> </ul> </li> <li> <p><code>split</code>相关事项</p> <ul> <li>有2个参数, 第2个表示数组最大长度 <pre><code>// ["js", "css"] 'js,css,html'.split(/,/, 2) </code></pre> </li> <li>使用分组, 则结果包含分隔符本身 <pre><code>// ["js", ",", "css", ",", "html"] 'js,css,html'.split(/(,)/) </code></pre> </li> </ul> </li> <li> <p><code>replace</code>很强大</p> <ul> <li> <p>第二个参数是字符串时, 有如下含义</p> <table> <thead> <tr> <th>属性</th> <th>描述</th> </tr> </thead> <tbody> <tr> <td> 2,...,$99</td> <td>匹配第1~99个分组里捕获到的文本</td> </tr> <tr> <td>$&</td> <td>匹配到的子串文本</td> </tr> <tr> <td>$`</td> <td>匹配到的子串左边的文本</td> </tr> <tr> <td>$'</td> <td>匹配到的子串右边的文本</td> </tr> <tr> <td>$$</td> <td>美元符号</td> </tr> </tbody> </table> <ul> <li>把<code>2,3,5</code>变成<code>5=2+3</code> <pre><code>// "5=2+3" '2,3,5'.replace(/(\d+),(\d+),(\d+)/, '$3=$1+$2') </code></pre> </li> <li>把<code>2,3,5</code>变成<code>222,333,555</code> <pre><code>'2,3,5'.replace(/(\d+)/g, '$&$&$&') </code></pre> </li> <li>把<code>2+3=5</code>变成<code>2+3=2+3=5=5</code> <pre><code>// "2+3=2+3=5=5" '2+3=5'.replace(/(=)/, "$&$`$&$'$&") </code></pre> </li> </ul> </li> <li> <p>第二个参数是函数时</p> <blockquote> <p><code>replace</code>此时拿到的信息比<code>exec</code>多</p> </blockquote> <pre><code>// ["1234", "1", "4", 0, "1234 2345 3456"] // ["2345", "2", "5", 5, "1234 2345 3456"] // ["3456", "3", "6", 10, "1234 2345 3456"] "1234 2345 3456".replace(/(\d)\d{2}(\d)/g, function (match, $1, $2, index, input) { // $1是每组数字的开始 // $2是每组数字的结束 console.log([match, $1, $2, index, input]); }) </code></pre> </li> </ul> </li> <li> <p>使用构造函数需要注意的问题</p> <blockquote> <p>不推荐使用, 会写很多的<code>\</code></p> </blockquote> <pre><code>// ["2017-06-27", "2017.06.27", "2017/06/27"] '2017-06-27 2017.06.27 2017/06/27'.match(/\d{4}(-|\.|\/)\d{2}\1\d{2}/g) // ["2017-06-27", "2017.06.27", "2017/06/27"] '2017-06-27 2017.06.27 2017/06/27'.match(new RegExp('\\d{4}(-|\\.|\\/)\\d{2}\\1\\d{2}', 'g')) </code></pre> </li> <li> <p>修饰符</p> <table> <thead> <tr> <th>修饰符</th> <th>描述</th> <th>单词</th> </tr> </thead> <tbody> <tr> <td>/g/</td> <td>全局匹配(找到所有的)</td> <td>global</td> </tr> <tr> <td>/i/</td> <td>忽略字母大小写</td> <td>ignoreCase</td> </tr> <tr> <td>/m/</td> <td>多行匹配, 只影响<code>^</code>和<code>$</code>, 二者变成行概念(行开头、行结尾)</td> <td>multiline</td> </tr> </tbody> </table> <ul> <li>只读属性 <pre><code>var regex = /\w/img // true console.log(regex.global) // true console.log(regex.ignoreCase) // true console.log(regex.multiline) </code></pre> </li> </ul> </li> <li> <p><code>source</code>属性</p> <blockquote> <p>对象属性, 除了<code>global</code>, <code>ignoreCase</code>, <code>multiline</code>, <code>lastIndex</code>还有<code>source</code>属性; 用来构建动态正则, 或确认真正的正则</p> </blockquote> <pre><code>var className = "high"; // => (^|\s)high(\s|$) // => 即字符串"(^|\\s)high(\\s|$)" var regex = new RegExp("(^|\\s)" + className + "(\\s|$)"); console.log( regex.source ) console.log(regex.test(' high '), regex.test('high')) </code></pre> </li> <li> <p>构造函数属性</p> <blockquote> <p>静态属性随着最后一次正则操作而变化, 除了<code>$1,...$9</code>, 还有几个不太常用的(有兼容问题)</p> </blockquote> <table> <thead> <tr> <th>静态属性</th> <th>描述</th> <th>简写形式</th> </tr> </thead> <tbody> <tr> <td><code>RegExp.input</code></td> <td>最近一次目标字符串</td> <td>RegExp['$_']</td> </tr> <tr> <td><code>RegExp.lastMatch</code></td> <td>最近一次匹配的文本</td> <td>RegExp['$&']</td> </tr> <tr> <td><code>RegExp.lastParen</code></td> <td>最近一次捕获的文本</td> <td>RegExp['$+']</td> </tr> <tr> <td><code>RegExp.leftContext</code></td> <td>目标匹配lastMatch之前的文本</td> <td>RegExp['$`']</td> </tr> <tr> <td><code>RegExp.rightContext</code></td> <td>目标匹配lastMatch之后的文本</td> <td>RegExp["$'"]</td> </tr> </tbody> </table> <pre><code>var regex = /([abc])(\d)/g var string = 'a1b2c3d4e5' string.match(regex) // a1b2c3d4e5 a1b2c3d4e5 console.log(RegExp.input, RegExp['$_']) // c3 c3 console.log(RegExp.lastMatch, RegExp['$&']) // 3 3 console.log(RegExp.lastParen, RegExp['$+']) // a1b2 c3 console.log(RegExp.leftContext, RegExp['$&']) // d4e5 d4e5 console.log(RegExp.rightContext, RegExp["$'"]) ``` </code></pre> </li> </ul> <h3>真实案例</h3> <ul> <li>构造函数生成正则: 通过class获取dom <pre><code>function getClassByName(className) { var elements = document.getElementByTagName('*') var regex = new RegExp('(^|\\s)' + className + '($|\\s)') var result = [] var elementsLength = elements.length for (var i = 0; i < elementsLength; i++) { var element = elements[i] if (regex.test(element.className)) { result.push(element) } } return result } </code></pre> </li> <li>字符串保存数据: 判断数据类型 <pre><code>var utils = {} 'Boolean|Number|String|Function|Array|Date|RegExp|Object|Error'.split('|').forEach(function(item) { utils['is' + item] = function(obj) { return {}.toString.call(obj) === '[object '+ item +']' } }) console.log(utils.isArray([1, 2, 3])) </code></pre> </li> <li>正则替代 &&(不兼容IE) <pre><code>var readyRegex = /complete|loaded|interactive/ function ready(callback) { if (readyRegex.test(document.readyState) && document.body) { callback() } else { document.addEventListener('DomContentLoaded', function() { callback() }, false) } } </code></pre> </li> <li>强大的replace: 参数查询压缩 <pre><code>function compress(source) { var keys = {} // [^=&]中的&不能去掉, 否则第二次会匹配成&b=2 // key不能为空, value有可能为空, 所以第一次是+, 第二次是* source.replace(/([^=&]+)=([^&])*/g, function(full, key, value) { keys[key] = (keys[key] ? keys[key] + ',' : '') + value }) var result = [] for (var key in keys) { result.push(key + '=' + keys[key]) } return result.join('&') } // a=1,3&b=2,4 console.log(compress('a=1&b=2&a=3&b=4')) </code></pre> </li> <li>根据字符串生成正则 <pre><code>function createRegex(regex) { try { if (regex[0] === '/') { regex = regex.split('/') regex.shift() var flags = regex.pop() regex = regex.join('/') regex = new RegExp(regex, flags) } else { regex = new RegExp(regex, 'g') } return { success: true, result: regex } } catch (e) { return { success: false, message: '无效的正则表达式' } } } // {success: true, result: /\d/gm} console.log(createRegex('/\\d/gm')) // {success: true, result: /\d/g} console.log(createRegex('/\\d/g')) </code></pre> </li> </ul> <h2>参考资料</h2> <ul> <li>教程类 <ul> <li> 《JavaScript 正则表达式迷你书》 <ul> <li>JS正则表达式完整教程-老姚</li> </ul> </li> <li>这次不会说我的正则教程没写全了吧??</li> </ul> </li> <li>文档类 <ul> <li>正则表达式简明参考</li> <li>正则表达式</li> <li>不包含某个字符</li> <li>至少包含某个字符</li> <li>最全的常用正则表达式大全——包括校验数字、字符、一些特殊的需求等等</li> </ul> </li> <li>实用? <ul> <li>网址校验 <ul> <li>验证类</li> <li>JavaScript正则编写-原理篇</li> </ul> </li> </ul> </li> <li>工具 <ul> <li> regexper: 正则可视化网站</li> </ul> </li> </ul> </article> </div> </div> </div> <!--PC和WAP自适应版--> <div id="SOHUCS" sid="1647261315128922112"></div> <script type="text/javascript" src="/views/front/js/chanyan.js"></script> <!-- 文章页-底部 动态广告位 --> <div class="youdao-fixed-ad" id="detail_ad_bottom"></div> </div> <div class="col-md-3"> <div class="row" id="ad"> <!-- 文章页-右侧1 动态广告位 --> <div id="right-1" class="col-lg-12 col-md-12 col-sm-4 col-xs-4 ad"> <div class="youdao-fixed-ad" id="detail_ad_1"> </div> </div> <!-- 文章页-右侧2 动态广告位 --> <div id="right-2" class="col-lg-12 col-md-12 col-sm-4 col-xs-4 ad"> <div class="youdao-fixed-ad" id="detail_ad_2"></div> </div> <!-- 文章页-右侧3 动态广告位 --> <div id="right-3" class="col-lg-12 col-md-12 col-sm-4 col-xs-4 ad"> <div class="youdao-fixed-ad" id="detail_ad_3"></div> </div> </div> </div> </div> </div> </div> <div class="container"> <h4 class="pt20 mb15 mt0 border-top">你可能感兴趣的:(《JavaScript正则表达式迷你书》读书笔记)</h4> <div id="paradigm-article-related"> <div class="recommend-post mb30"> <ul class="widget-links"> <li><a href="/article/1950232820773351424.htm" title="移动端城市区县二级联动选择功能实现包" target="_blank">移动端城市区县二级联动选择功能实现包</a> <span class="text-muted">good2know</span> <div>本文还有配套的精品资源,点击获取简介:本项目是一套为移动端设计的jQuery实现方案,用于简化用户在选择城市和区县时的流程。它包括所有必需文件:HTML、JavaScript、CSS及图片资源。通过动态更新下拉菜单选项,实现城市到区县的联动效果,支持数据异步加载。开发者可以轻松集成此功能到移动网站或应用,并可基于需求进行扩展和优化。1.jQuery移动端解决方案概述jQuery技术简介jQuery</div> </li> <li><a href="/article/1950232782412247040.htm" title="日更006 终极训练营day3" target="_blank">日更006 终极训练营day3</a> <span class="text-muted">懒cici</span> <div>人生创业课(2)今天的主题:学习方法一:遇到有用的书,反复读,然后结合自身实际,列践行清单,不要再写读书笔记思考这本书与我有什么关系,我在哪些地方能用到,之后我该怎么用方法二:读完书没映像怎么办?训练你的大脑,方法:每读完一遍书,立马合上书,做一场分享,几分钟都行对自己的学习要求太低,要逼自己方法三:学习深度不够怎么办?找到细分领域的榜样,把他们的文章、书籍、产品都体验一遍,成为他们的超级用户,向</div> </li> <li><a href="/article/1950229418706268160.htm" title="密码正则验证:大小写字母、数字、特殊字符至少8位" target="_blank">密码正则验证:大小写字母、数字、特殊字符至少8位</a> <span class="text-muted">qq_21875331</span> <a class="tag" taget="_blank" href="/search/%E6%B8%90%E8%BF%9B%E5%BC%8F%E7%9A%84%E6%88%90%E9%95%BF/1.htm">渐进式的成长</a> <div>正则表达式:密码必须包含大写字母、数字、特殊字符(四种里至少三种,且至少8位)写法一:/((^(?=.*[a-z])(?=.*[A-Z])(?=.*\W)[\da-zA-Z\W]{8,16}$)|(^(?=.*\d)(?=.*[A-Z])(?=.*\W)[\da-zA-Z\W]{8,16}$)|(^(?=.*\d)(?=.*[a-z])(?=.*\W)[\da-zA-Z\W]{8,16}$)|(^</div> </li> <li><a href="/article/1950220179610857472.htm" title="【花了N长时间读《过犹不及》,不断练习,可以越通透】" target="_blank">【花了N长时间读《过犹不及》,不断练习,可以越通透】</a> <span class="text-muted">君君Love</span> <div>我已经记不清花了多长时间去读《过犹不及》,读书笔记都写了42页,这算是读得特别精细的了。是一本难得的好书,虽然书中很多内容和圣经吻合,我不是基督徒,却觉得这样的文字值得细细品味,和我们的生活息息相关。我是个界线建立不牢固的人,常常愧疚,常常害怕他人的愤怒,常常不懂拒绝,还有很多时候表达不了自己真实的感受,心里在说不嘴里却在说好……这本书给我很多的启示,让我学会了怎样去建立属于自己的清晰的界限。建立</div> </li> <li><a href="/article/1950205034075582464.htm" title="《感官品牌》读书笔记 1" target="_blank">《感官品牌》读书笔记 1</a> <span class="text-muted">西红柿阿达</span> <div>原文:最近我在东京街头闲逛时,与一位女士擦肩而过,我发现她的香水味似曾相识。“哗”的一下,记亿和情感立刻像潮水般涌了出来。这个香水味把我带回了15年前上高中的时候,我的一位亲密好友也是用这款香水。一瞬间,我呆站在那里,东京的街景逐渐淡出,取而代之的是我年少时的丹麦以及喜悦、悲伤、恐惧、困惑的记忆。我被这熟悉的香水味征服了。感想:感官是有记忆的,你所听到,看到,闻到过的有代表性的事件都会在大脑中深深</div> </li> <li><a href="/article/1950194742100815872.htm" title="用代码生成艺术字:设计个性化海报的秘密" target="_blank">用代码生成艺术字:设计个性化海报的秘密</a> <span class="text-muted"></span> <div>本文围绕“用代码生成艺术字:设计个性化海报的秘密”展开,先概述代码生成艺术字在海报设计中的独特价值,接着介绍常用的代码工具(如HTML、CSS、JavaScript等),详细阐述从构思到实现的完整流程,包括字体样式设计、动态效果添加等,还分享了提升艺术字质感的技巧及实际案例。最后总结代码生成艺术字的优势,为设计师提供打造个性化海报的实用指南,助力提升海报设计的独特性与吸引力,符合搜索引擎SEO标准</div> </li> <li><a href="/article/1950165603524341760.htm" title="《如何写作》文心读书笔记" target="_blank">《如何写作》文心读书笔记</a> <span class="text-muted">逆熵反弹力</span> <div>《文心》这本书的文体是以讲故事的形式来讲解如何写作的,读起来不会觉得刻板。读完全书惊叹大师的文笔如此之好,同时感叹与此书相见恨晚。工作了几年发现表达能力在生活中越来越重要,不管是口语还是文字上的表达。有时候甚至都不能把自己想说的东西表达清楚,平时也有找过一些书来看,想通过提升自己的阅读量来提高表达能力。但是看了这么久的书发现见效甚微,这使得我不得不去反思,该怎么提高表达能力。因此打算从写作入手。刚</div> </li> <li><a href="/article/1950144218282389504.htm" title="为什么学习Web前端一定要掌握JavaScript?" target="_blank">为什么学习Web前端一定要掌握JavaScript?</a> <span class="text-muted">web前端学习指南</span> <div>为什么学习Web前端一定要掌握JavaScript?在前端的世界里,没有什么是JavaScript实现不了的,关于JS有一句话:凡是可以用JavaScript来写的应用,最终都会用JavaScript,JavaScript可运行在所有主要平台的所有主流浏览器上,也可运行在每一个主流操作系统的服务器端上。现如今我们在为网站写任何一个主要功能的时候都需要有懂能够用JavaScript写前端的开发人员。</div> </li> <li><a href="/article/1950135315482079232.htm" title="【208】《班级管理课》读书感悟(一百零五)2023-07-23" target="_blank">【208】《班级管理课》读书感悟(一百零五)2023-07-23</a> <span class="text-muted">南风如我意</span> <div>-----------《班级管理课》读书感悟四文/李现风2023年读书笔记读书笔记以以下三个出发点为目的:一、书中的思想,提升自己的教育理念;二、书中的值得借鉴的做法,提升自己的教育技巧;三、书中的美句,有鉴于哲理性的句子,提升自己文章的语言魅力和教育文化水准。读《班级管理课》作者陈宇读书感悟四:【书目】《班级管理课》【页数】第70页第87页【阅读内容(摘录)】第四课开学一个月:班级常规工作正常运</div> </li> <li><a href="/article/1950130692448907264.htm" title="Vue CSR 到 Nuxt 3 SSR 迁移:技术实现与问题解决实录" target="_blank">Vue CSR 到 Nuxt 3 SSR 迁移:技术实现与问题解决实录</a> <span class="text-muted">二倍速播放</span> <a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF/1.htm">前端</a><a class="tag" taget="_blank" href="/search/vue.js/1.htm">vue.js</a> <div>1.迁移动机与技术选型1.1CSR架构的局限性基于Vue3和Vite构建的客户端渲染(CSR)单页应用(SPA)提供了良好的开发体验和用户交互流畅性。但是其核心局限在于:搜索引擎优化(SEO):初始HTML响应仅包含一个根div元素,实际内容由JavaScript在浏览器端动态生成。虽然主流搜索引擎(如Google)能够执行部分JavaScript,但其抓取效率和稳定性不如直接获取完整HTML。非</div> </li> <li><a href="/article/1950114810557427712.htm" title="12. 什么是事件委托" target="_blank">12. 什么是事件委托</a> <span class="text-muted">yqcoder</span> <a class="tag" taget="_blank" href="/search/%E5%89%8D%E7%AB%AF%E9%9D%A2%E8%AF%95-CSS/1.htm">前端面试-CSS</a><a class="tag" taget="_blank" href="/search/css/1.htm">css</a><a class="tag" taget="_blank" href="/search/%E9%9D%A2%E8%AF%95/1.htm">面试</a> <div>总结事件委托(EventDelegation)是JavaScript中一种重要的事件处理机制,它利用了事件冒泡的特性,将事件的处理程序绑定到父元素或祖先元素上,而不是直接绑定到具体的子元素上。什么是事件委托?事件冒泡:在DOM中,事件通常会从触发元素开始,然后逐级向上冒泡到其父元素、祖先元素,直到window对象。核心思想:事件委托的核心思想是利用事件冒泡机制,在父元素上监听事件,而不是在每个子元</div> </li> <li><a href="/article/1950096980860530688.htm" title="D020+3组鱼来与鱼往+《吉田医生哈佛求学记》读书笔记" target="_blank">D020+3组鱼来与鱼往+《吉田医生哈佛求学记》读书笔记</a> <span class="text-muted">筱麦</span> <div>今天读第四章时,看到一句话:只要不放弃,就能发现道路,即便是羊肠小道。这让我想起那年去集安玩的经历,那年夏天我们三口人自驾去集安玩,玩的几天特别开心,夏季多雨,返程的时候,就赶上了大雨,雨势迅猛,任凭雨刷器摆的再快,也看不清前方的路,而且有一段路是盘山路,特别陡特别窄,在这样的路况下,女儿有些害怕,我心里也很紧张,老公劝我们说没事的,虽然他这么说,但我还是很紧张,坐在副驾驶专心替他看路。开过了盘山</div> </li> <li><a href="/article/1950084903089532928.htm" title="03《孙子兵法<谋攻篇>》:全胜论---成年人该有的战略意识" target="_blank">03《孙子兵法<谋攻篇>》:全胜论---成年人该有的战略意识</a> <span class="text-muted">弓長言兑</span> <div>承接前面的读书笔记,我们通过《孙子兵法》第一篇的《计篇》,了解到兵圣孙武“慎战论”的观点,并且知道了什么是“五事”、“七计”、“十二术”。通过第二篇《作战篇》,从经济学的角度,我们领悟了孙子为什么强调“速战论”,以及增利减害、以战养战的光辉思想。今天我们一起探讨《孙子兵法》第三篇《谋攻篇》。看看兵圣孙武又将带给我们怎样的智慧。老规矩,精选经典论述,让大家先读为快。1.好句共读:“凡用兵之法,全国为</div> </li> <li><a href="/article/1950075480849838080.htm" title="关于前端的性能优化" target="_blank">关于前端的性能优化</a> <span class="text-muted"></span> <div>性能优化主要涵盖了以下四个方面:(tip:仅代表个人总结,如有不当,还希望看到的大佬多多指示)减少网络请求:合并文件、使用CDN、启用缓存。优化资源加载:代码分割、懒加载、图片压缩。提升渲染性能:减少重绘回流、防抖节流、使用WebWorker。监控和迭代:定期使用工具检测性能,持续优化。一、网络层面优化减少HTTP请求合并文件:将多个CSS或JavaScript文件合并成一个,减少请求次数。使用C</div> </li> <li><a href="/article/1950074224618041344.htm" title="【读书笔记】《一课经济学》经济学艺术" target="_blank">【读书笔记】《一课经济学》经济学艺术</a> <span class="text-muted">Cynthiayumoon</span> <div>经济学•艺术文|雯雨霏【选摘】作者:亨利·黑兹利特本书目的:为了强调一般性的经济学原理,强调忽视这些原理会受到的惩罚。本书主旨:分析经济生活中盛行的一些谬论。第一部分:主旨•忽视那些不那么即时和不那么明显的后果,本身就是一个谬误。•经济学的艺术,在于不仅要观察任何行为或政策的即时影响,更要考察其比较长远的影响;不仅要关注政策对某个群体产生的影响,更要追踪其对所有群体造成的影响。•学会如何发现和避开</div> </li> <li><a href="/article/1950074093608955904.htm" title="时间组件库Day.js那些事" target="_blank">时间组件库Day.js那些事</a> <span class="text-muted">前端小白花</span> <a class="tag" taget="_blank" href="/search/javascript/1.htm">javascript</a><a class="tag" taget="_blank" href="/search/%E5%BC%80%E5%8F%91%E8%AF%AD%E8%A8%80/1.htm">开发语言</a><a class="tag" taget="_blank" href="/search/ecmascript/1.htm">ecmascript</a> <div>一、简介1.什么是Day.jsDay.js是一个轻量级,易于使用的JavaScript日期库,提供了强大的日期和时间处理功能,与Moment.js的API设计相似,但具有更高的性能和更小的体积。Day.js官网https://day.js.org/docs/zh-CN/installation/installation2.优势a.特点轻量级:Dayjs的压缩后大小只有2KB左右,远小于Moment</div> </li> <li><a href="/article/1950071066281963520.htm" title="JavaScript正则表达式去除括号但保留内容与去除括号与内容" target="_blank">JavaScript正则表达式去除括号但保留内容与去除括号与内容</a> <span class="text-muted">Selicens</span> <a class="tag" taget="_blank" href="/search/javascript/1.htm">javascript</a><a class="tag" taget="_blank" href="/search/%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F/1.htm">正则表达式</a> <div>项目上碰到一个需求,是取多个递增文件的文件名,类似于test(1).txt、test(2).txt,但是不需要括号,只要test1、test2这种格式,最开始想到的办法就是js里的replace替换,先上一个比较笨但是也能实现效果的例子letname="test(1).txt"letdata=name.split('.')[0].replace('(','').replace(')','')con</div> </li> <li><a href="/article/1950060325839630336.htm" title="读书笔记6‖《怎样开会》" target="_blank">读书笔记6‖《怎样开会》</a> <span class="text-muted">知微呀</span> <div>昨天梳理的第五、第六讲内容竟然被锁了,管它呢,我的目的是梳理读书内容,便于吸收记忆,管它锁不锁,我只管做就是了!今天继续第七讲和第八讲内容。第七讲:决策会1.提请决策的议题应当基本成熟通过开会作决策是会议的一项基本功能,也是极为重要的核心功能。决策正确则会议正确,决策失误则意味着会议根本失误。正常情况下,提请会议决策的议题都应是基本成熟的,并且要经过事先审核和协调沟通。日常工作中的具体决策,不一定</div> </li> <li><a href="/article/1950046460212998144.htm" title="2022-11-13#看书笔记#成长#《我的第一本人生规划手册》" target="_blank">2022-11-13#看书笔记#成长#《我的第一本人生规划手册》</a> <span class="text-muted">萧瑟归去</span> <div>本书的基本信息来源:微信读书APP种类:付费书籍说明符号:>>为划线的原文部分,例如:>为上一句无符号为想法部分,>为想法选中的原文部分,例如:读书笔记如下:序>>当我们把任何计划,加上“管理”两个字,立刻就可以变得高大上起来,比如说:“身材管理”“时间管理”“财富管理”“读书管理”“思维管理”,等等。将目标具体化,将计划具体化,其实是一个思维转化的问题>从“语文思维”到“数学思维”的转变计划安排</div> </li> <li><a href="/article/1950042324155297792.htm" title="网络安全第14集" target="_blank">网络安全第14集</a> <span class="text-muted">不灭锦鲤</span> <a class="tag" taget="_blank" href="/search/web%E5%AE%89%E5%85%A8/1.htm">web安全</a><a class="tag" taget="_blank" href="/search/%E5%AE%89%E5%85%A8/1.htm">安全</a> <div>前言:小迪安全14集,这集重点内容:0、什么是js渗透测试?在javascript中也存在变量和函数,存在可控变量和函数就有可能存在在漏洞,js开发的web应用和php、java开发的区别是,js能看得到的源代码,php看不到,但是风险就是未授权访问、配置信息泄露(加密算法、key秘钥等),源代码看得到,存在更多的url泄露,从而可能会出现未授权访问,从url,前提:web应用可以采用前端语言或后</div> </li> <li><a href="/article/1950040812469415936.htm" title="25年不倒的“犀牛书“:为什么《JavaScript权威指南第7版》仍是程序员的案头圣经?" target="_blank">25年不倒的“犀牛书“:为什么《JavaScript权威指南第7版》仍是程序员的案头圣经?</a> <span class="text-muted">阿蒙Armon</span> <a class="tag" taget="_blank" href="/search/javascript/1.htm">javascript</a><a class="tag" taget="_blank" href="/search/%E5%BC%80%E5%8F%91%E8%AF%AD%E8%A8%80/1.htm">开发语言</a><a class="tag" taget="_blank" href="/search/ecmascript/1.htm">ecmascript</a> <div>25年不倒的"犀牛书":为什么《JavaScript权威指南第7版》仍是程序员的案头圣经?当一本技术书能连续畅销25年,历经7次迭代仍稳坐领域第一梯队,它必然藏着超越时代的硬实力。《JavaScript权威指南(原书第7版)》就是这样一部传奇——豆瓣9.4分的封神之作,程序员口中的"犀牛书",从网景时代到ES2020,它始终是JavaScript开发者的终极参考书。如果你还在为原型链、闭包、异步编</div> </li> <li><a href="/article/1950013982886653952.htm" title="分享今日读书笔记" target="_blank">分享今日读书笔记</a> <span class="text-muted">小朗_18f9</span> <div>设计治疗抑郁症的新方法。我们的理由很简单。既然抑郁症来自一个长期养成的消极思维模式,那如果我们可以改变这种思维模式,我们就可以治疗抑郁症。你怎样看问题决定了你是否能从抑郁中解脱出来,或者使抑郁更加严重。一次失败或打击会告诉你,你现在是无助的,但习得性无助只会造成暂时的抑郁,除非你有悲观的解释风格。</div> </li> <li><a href="/article/1949995914462556160.htm" title="什么是JSON,如何与Java对象转化" target="_blank">什么是JSON,如何与Java对象转化</a> <span class="text-muted">doublez234</span> <a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/json/1.htm">json</a><a class="tag" taget="_blank" href="/search/spring/1.htm">spring</a><a class="tag" taget="_blank" href="/search/spring/1.htm">spring</a><a class="tag" taget="_blank" href="/search/boot/1.htm">boot</a> <div>JSON概念JSON(JavaScriptObjectNotation)是一种轻量级的数据交换格式。它易于人阅读和编写,同时也易于机器解析和生成。JSON基于JavaScript(ECMAScript(欧洲计算机协会制定的js规范))编程语言的一个子集,但它是一种独立于语言的数据格式,被广泛应用于各种编程语言和平台之间的数据交换。JSON的主要特点:轻量级:JSON格式非常简洁,只包含必要的数据信</div> </li> <li><a href="/article/1949989453242101760.htm" title="《你就是孩子最好的玩具》读书笔记" target="_blank">《你就是孩子最好的玩具》读书笔记</a> <span class="text-muted">许个诺</span> <div>一、父母管教孩子的常见误区1、控制型父母特征:”都给我停下来!不许乱跑!再捣乱就别想看电视!-命令和威胁是控制型的典型表现-这样不会让孩子有责任感,孩子长大后会更容易放纵自己。”2、放任型父母”不理他,我没办法,小孩子闹一闹没关系的。“”孩子学不会应有的社会规则-孩子长大会缺乏约束和规矩,没有群体归属感,更容易涉及毒品、早孕和帮派、网络成瘾。因为他们需要极强的团队依赖。”3、轻视、低估和否定孩子的</div> </li> <li><a href="/article/1949975484238458880.htm" title="APP开发入门:了解主流的编程语言" target="_blank">APP开发入门:了解主流的编程语言</a> <span class="text-muted">agi大模型</span> <a class="tag" taget="_blank" href="/search/Python/1.htm">Python</a><a class="tag" taget="_blank" href="/search/%E8%81%8C%E4%B8%9A%E4%B8%8E%E8%81%8C%E5%9C%BA/1.htm">职业与职场</a><a class="tag" taget="_blank" href="/search/%E7%A8%8B%E5%BA%8F%E5%91%98/1.htm">程序员</a><a class="tag" taget="_blank" href="/search/%E5%BC%80%E5%8F%91%E8%AF%AD%E8%A8%80/1.htm">开发语言</a><a class="tag" taget="_blank" href="/search/%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90/1.htm">数据分析</a><a class="tag" taget="_blank" href="/search/%E7%BC%96%E7%A8%8B%E8%AF%AD%E8%A8%80/1.htm">编程语言</a> <div>前言在过去的几年里,有许多程序员开始学习和使用编程语言。这其中包括C、C++、Java和Python。尽管有许多语言可供选择,但大多数程序员都会选择最容易学习的编程语言。如今,有很多编程语言供选择。程序员们在学习这些语言时可以自由地选择他们喜欢的方式,因为他们的目标是构建任何软件,而不仅仅是创建一个应用程序。你可以在Linux上学习C/C++、Java、Python、C#或JavaScript,你</div> </li> <li><a href="/article/1949934124164771840.htm" title="《剑指offer》-数据结构篇-哈希表/数组/矩阵/字符串" target="_blank">《剑指offer》-数据结构篇-哈希表/数组/矩阵/字符串</a> <span class="text-muted">小新学习屋</span> <a class="tag" taget="_blank" href="/search/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B8%8E%E7%AE%97%E6%B3%95/1.htm">数据结构与算法</a><a class="tag" taget="_blank" href="/search/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/1.htm">数据结构</a><a class="tag" taget="_blank" href="/search/leetcode/1.htm">leetcode</a><a class="tag" taget="_blank" href="/search/%E5%93%88%E5%B8%8C%E8%A1%A8/1.htm">哈希表</a> <div>题目第一个只出现一次的字符数组中的重复的数字字符串流中第一个不重复的字符数组中只出现一次的数字调整数组顺序使奇数位于偶数前面数组中出现次数超过一半的数字把数组排成最小的数顺时针打印矩阵把字符串转换为整数表示数值的字符串左旋转字符串(矩阵翻转)替换空格正则表达式匹配代码实现第一个只出现一次的字符题目描述:在一个字符串(0len(numbers)/2:returnreselse:return0把数组排</div> </li> <li><a href="/article/1949928456414359552.htm" title="探秘CommonJS:Node.js模块化核心解析" target="_blank">探秘CommonJS:Node.js模块化核心解析</a> <span class="text-muted"></span> <div>CommonJS是JavaScript的模块化规范,主要应用于服务器端环境(尤其是Node.js),其核心目标是解决代码组织、依赖管理和作用域隔离问题。以下是其核心要点:一、核心特性同步加载模块通过require()同步加载并执行,后续代码需等待模块加载完成后执行,适用于I/O快速的服务器环境(如本地文件读取)。作用域隔离每个文件视为独立模块,模块内定义的变量、函数默认私有(不污染全局作用域),仅</div> </li> <li><a href="/article/1949928204164722688.htm" title="【通识】正则表达式" target="_blank">【通识】正则表达式</a> <span class="text-muted"></span> <div>1.正则表达式基本概念:正规表示/常规表示(RegularExpress)1)使用单个字符串描述、匹配一系列符合某个句法规则的字符串。在很多文本编辑器中,正则表达式通常被用来检索、替换符合某个模式的文本2)元字符和描述元字符描述\将下一个字符标记为特殊字符、或一个原义字符、或一个向后引用、或一个八进制等112.正则表达式的应用1111511</div> </li> <li><a href="/article/1949926944988524544.htm" title="壹脉销客AI电子名片源码核心架构" target="_blank">壹脉销客AI电子名片源码核心架构</a> <span class="text-muted"></span> <div>为什么选择源码部署AI电子名片?在数字化转型浪潮中,越来越多的企业意识到拥有自主可控的电子名片系统的重要性。源码部署相比SaaS服务具有三大核心优势:数据完全自主-客户信息存储在企业自有服务器深度定制自由-可根据业务需求二次开发长期成本优化-一次部署永久使用壹脉销客AI电子名片源码核心架构壹脉销客提供的企业级电子名片解决方案采用前后端分离架构:前端技术栈(小程序端)javascript//小程序a</div> </li> <li><a href="/article/1949918371738873856.htm" title="vue 进入一个页面,然后离开这个页面他就重新加载" target="_blank">vue 进入一个页面,然后离开这个页面他就重新加载</a> <span class="text-muted">Java&Develop</span> <a class="tag" taget="_blank" href="/search/vue/1.htm">vue</a><a class="tag" taget="_blank" href="/search/vue/1.htm">vue</a> <div>vue进入一个页面,然后离开这个页面他就重新加载这个代码导致的注释即可window.location.reload();window.location.reload()是JavaScript中的一个方法,用于强制刷新当前页面(重新加载页面内容)。其作用类似于用户手动点击浏览器的刷新按钮,但可以通过代码精确触发。核心作用:刷新页面重新加载当前显示的文档(即重新请求当前URL的资源)。可选参数控制缓存</div> </li> <li><a href="/article/77.htm" title="算法 单链的创建与删除" target="_blank">算法 单链的创建与删除</a> <span class="text-muted">换个号韩国红果果</span> <a class="tag" taget="_blank" href="/search/c/1.htm">c</a><a class="tag" taget="_blank" href="/search/%E7%AE%97%E6%B3%95/1.htm">算法</a> <div> 先创建结构体 struct student { int data; //int tag;//标记这是第几个 struct student *next; }; // addone 用于将一个数插入已从小到大排好序的链中 struct student *addone(struct student *h,int x){ if(h==NULL) //?????? </div> </li> <li><a href="/article/204.htm" title="《大型网站系统与Java中间件实践》第2章读后感" target="_blank">《大型网站系统与Java中间件实践》第2章读后感</a> <span class="text-muted">白糖_</span> <a class="tag" taget="_blank" href="/search/java%E4%B8%AD%E9%97%B4%E4%BB%B6/1.htm">java中间件</a> <div>       断断续续花了两天时间试读了《大型网站系统与Java中间件实践》的第2章,这章总述了从一个小型单机构建的网站发展到大型网站的演化过程---整个过程会遇到很多困难,但每一个屏障都会有解决方案,最终就是依靠这些个解决方案汇聚到一起组成了一个健壮稳定高效的大型系统。          看完整章内容,</div> </li> <li><a href="/article/331.htm" title="zeus持久层spring事务单元测试" target="_blank">zeus持久层spring事务单元测试</a> <span class="text-muted">deng520159</span> <a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/DAO/1.htm">DAO</a><a class="tag" taget="_blank" href="/search/spring/1.htm">spring</a><a class="tag" taget="_blank" href="/search/jdbc/1.htm">jdbc</a> <div>今天把zeus事务单元测试放出来,让大家指出他的毛病, 1.ZeusTransactionTest.java 单元测试   package com.dengliang.zeus.webdemo.test; import java.util.ArrayList; import java.util.List; import org.junit.Test; import </div> </li> <li><a href="/article/458.htm" title="Rss 订阅 开发" target="_blank">Rss 订阅 开发</a> <span class="text-muted">周凡杨</span> <a class="tag" taget="_blank" href="/search/html/1.htm">html</a><a class="tag" taget="_blank" href="/search/xml/1.htm">xml</a><a class="tag" taget="_blank" href="/search/%E8%AE%A2%E9%98%85/1.htm">订阅</a><a class="tag" taget="_blank" href="/search/rss/1.htm">rss</a><a class="tag" taget="_blank" href="/search/%E8%A7%84%E8%8C%83/1.htm">规范</a> <div>                RSS是 Really Simple Syndication的缩写(对rss2.0而言,是这三个词的缩写,对rss1.0而言则是RDF Site Summary的缩写,1.0与2.0走的是两个体系)。   RSS</div> </li> <li><a href="/article/585.htm" title="分页查询实现" target="_blank">分页查询实现</a> <span class="text-muted">g21121</span> <a class="tag" taget="_blank" href="/search/%E5%88%86%E9%A1%B5%E6%9F%A5%E8%AF%A2/1.htm">分页查询</a> <div>在查询列表时我们常常会用到分页,分页的好处就是减少数据交换,每次查询一定数量减少数据库压力等等。 按实现形式分前台分页和服务器分页: 前台分页就是一次查询出所有记录,在页面中用js进行虚拟分页,这种形式在数据量较小时优势比较明显,一次加载就不必再访问服务器了,但当数据量较大时会对页面造成压力,传输速度也会大幅下降。 服务器分页就是每次请求相同数量记录,按一定规则排序,每次取一定序号直接的数据</div> </li> <li><a href="/article/712.htm" title="spring jms异步消息处理" target="_blank">spring jms异步消息处理</a> <span class="text-muted">510888780</span> <a class="tag" taget="_blank" href="/search/jms/1.htm">jms</a> <div>spring JMS对于异步消息处理基本上只需配置下就能进行高效的处理。其核心就是消息侦听器容器,常用的类就是DefaultMessageListenerContainer。该容器可配置侦听器的并发数量,以及配合MessageListenerAdapter使用消息驱动POJO进行消息处理。且消息驱动POJO是放入TaskExecutor中进行处理,进一步提高性能,减少侦听器的阻塞。具体配置如下: </div> </li> <li><a href="/article/839.htm" title="highCharts柱状图" target="_blank">highCharts柱状图</a> <span class="text-muted">布衣凌宇</span> <a class="tag" taget="_blank" href="/search/hightCharts/1.htm">hightCharts</a><a class="tag" taget="_blank" href="/search/%E6%9F%B1%E5%9B%BE/1.htm">柱图</a> <div>第一步:导入 exporting.js,grid.js,highcharts.js;第二步:写controller   @Controller@RequestMapping(value="${adminPath}/statistick")public class StatistickController {  private UserServi</div> </li> <li><a href="/article/966.htm" title="我的spring学习笔记2-IoC(反向控制 依赖注入)" target="_blank">我的spring学习笔记2-IoC(反向控制 依赖注入)</a> <span class="text-muted">aijuans</span> <a class="tag" taget="_blank" href="/search/spring/1.htm">spring</a><a class="tag" taget="_blank" href="/search/mvc/1.htm">mvc</a><a class="tag" taget="_blank" href="/search/Spring+%E6%95%99%E7%A8%8B/1.htm">Spring 教程</a><a class="tag" taget="_blank" href="/search/spring3+%E6%95%99%E7%A8%8B/1.htm">spring3 教程</a><a class="tag" taget="_blank" href="/search/Spring+%E5%85%A5%E9%97%A8/1.htm">Spring 入门</a> <div>IoC(反向控制 依赖注入)这是Spring提出来了,这也是Spring一大特色。这里我不用多说,我们看Spring教程就可以了解。当然我们不用Spring也可以用IoC,下面我将介绍不用Spring的IoC。 IoC不是框架,她是java的技术,如今大多数轻量级的容器都会用到IoC技术。这里我就用一个例子来说明: 如:程序中有 Mysql.calss 、Oracle.class 、SqlSe</div> </li> <li><a href="/article/1093.htm" title="TLS java简单实现" target="_blank">TLS java简单实现</a> <span class="text-muted">antlove</span> <a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/ssl/1.htm">ssl</a><a class="tag" taget="_blank" href="/search/keystore/1.htm">keystore</a><a class="tag" taget="_blank" href="/search/tls/1.htm">tls</a><a class="tag" taget="_blank" href="/search/secure/1.htm">secure</a> <div>  1. SSLServer.java package ssl; import java.io.FileInputStream; import java.io.InputStream; import java.net.ServerSocket; import java.net.Socket; import java.security.KeyStore; import </div> </li> <li><a href="/article/1220.htm" title="Zip解压压缩文件" target="_blank">Zip解压压缩文件</a> <span class="text-muted">百合不是茶</span> <a class="tag" taget="_blank" href="/search/Zip%E6%A0%BC%E5%BC%8F%E8%A7%A3%E5%8E%8B/1.htm">Zip格式解压</a><a class="tag" taget="_blank" href="/search/Zip%E6%B5%81%E7%9A%84%E4%BD%BF%E7%94%A8/1.htm">Zip流的使用</a><a class="tag" taget="_blank" href="/search/%E6%96%87%E4%BB%B6%E8%A7%A3%E5%8E%8B/1.htm">文件解压</a> <div>   ZIP文件的解压缩实质上就是从输入流中读取数据。Java.util.zip包提供了类ZipInputStream来读取ZIP文件,下面的代码段创建了一个输入流来读取ZIP格式的文件; ZipInputStream in = new ZipInputStream(new FileInputStream(zipFileName));     &n</div> </li> <li><a href="/article/1347.htm" title="underscore.js 学习(一)" target="_blank">underscore.js 学习(一)</a> <span class="text-muted">bijian1013</span> <a class="tag" taget="_blank" href="/search/JavaScript/1.htm">JavaScript</a><a class="tag" taget="_blank" href="/search/underscore/1.htm">underscore</a> <div>        工作中需要用到underscore.js,发现这是一个包括了很多基本功能函数的js库,里面有很多实用的函数。而且它没有扩展 javascript的原生对象。主要涉及对Collection、Object、Array、Function的操作。       学</div> </li> <li><a href="/article/1474.htm" title="java jvm常用命令工具——jstatd命令(Java Statistics Monitoring Daemon)" target="_blank">java jvm常用命令工具——jstatd命令(Java Statistics Monitoring Daemon)</a> <span class="text-muted">bijian1013</span> <a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/jvm/1.htm">jvm</a><a class="tag" taget="_blank" href="/search/jstatd/1.htm">jstatd</a> <div>1.介绍         jstatd是一个基于RMI(Remove Method Invocation)的服务程序,它用于监控基于HotSpot的JVM中资源的创建及销毁,并且提供了一个远程接口允许远程的监控工具连接到本地的JVM执行命令。         jstatd是基于RMI的,所以在运行jstatd的服务</div> </li> <li><a href="/article/1601.htm" title="【Spring框架三】Spring常用注解之Transactional" target="_blank">【Spring框架三】Spring常用注解之Transactional</a> <span class="text-muted">bit1129</span> <a class="tag" taget="_blank" href="/search/transactional/1.htm">transactional</a> <div>Spring可以通过注解@Transactional来为业务逻辑层的方法(调用DAO完成持久化动作)添加事务能力,如下是@Transactional注解的定义:   /* * Copyright 2002-2010 the original author or authors. * * Licensed under the Apache License, Version </div> </li> <li><a href="/article/1728.htm" title="我(程序员)的前进方向" target="_blank">我(程序员)的前进方向</a> <span class="text-muted">bitray</span> <a class="tag" taget="_blank" href="/search/%E7%A8%8B%E5%BA%8F%E5%91%98/1.htm">程序员</a> <div>作为一个普通的程序员,我一直游走在java语言中,java也确实让我有了很多的体会.不过随着学习的深入,java语言的新技术产生的越来越多,从最初期的javase,我逐渐开始转变到ssh,ssi,这种主流的码农,.过了几天为了解决新问题,webservice的大旗也被我祭出来了,又过了些日子jms架构的activemq也开始必须学习了.再后来开始了一系列技术学习,osgi,restful.....</div> </li> <li><a href="/article/1855.htm" title="nginx lua开发经验总结" target="_blank">nginx lua开发经验总结</a> <span class="text-muted">ronin47</span> <div>使用nginx lua已经两三个月了,项目接开发完毕了,这几天准备上线并且跟高德地图对接。回顾下来lua在项目中占得必中还是比较大的,跟PHP的占比差不多持平了,因此在开发中遇到一些问题备忘一下 1:content_by_lua中代码容量有限制,一般不要写太多代码,正常编写代码一般在100行左右(具体容量没有细心测哈哈,在4kb左右),如果超出了则重启nginx的时候会报 too long pa</div> </li> <li><a href="/article/1982.htm" title="java-66-用递归颠倒一个栈。例如输入栈{1,2,3,4,5},1在栈顶。颠倒之后的栈为{5,4,3,2,1},5处在栈顶" target="_blank">java-66-用递归颠倒一个栈。例如输入栈{1,2,3,4,5},1在栈顶。颠倒之后的栈为{5,4,3,2,1},5处在栈顶</a> <span class="text-muted">bylijinnan</span> <a class="tag" taget="_blank" href="/search/java/1.htm">java</a> <div> import java.util.Stack; public class ReverseStackRecursive { /** * Q 66.颠倒栈。 * 题目:用递归颠倒一个栈。例如输入栈{1,2,3,4,5},1在栈顶。 * 颠倒之后的栈为{5,4,3,2,1},5处在栈顶。 *1. Pop the top element *2. Revers</div> </li> <li><a href="/article/2109.htm" title="正确理解Linux内存占用过高的问题" target="_blank">正确理解Linux内存占用过高的问题</a> <span class="text-muted">cfyme</span> <a class="tag" taget="_blank" href="/search/linux/1.htm">linux</a> <div>Linux开机后,使用top命令查看,4G物理内存发现已使用的多大3.2G,占用率高达80%以上: Mem:   3889836k total,  3341868k used,   547968k free,   286044k buffers Swap:  6127608k total,&nb</div> </li> <li><a href="/article/2236.htm" title="[JWFD开源工作流]当前流程引擎设计的一个急需解决的问题" target="_blank">[JWFD开源工作流]当前流程引擎设计的一个急需解决的问题</a> <span class="text-muted">comsci</span> <a class="tag" taget="_blank" href="/search/%E5%B7%A5%E4%BD%9C%E6%B5%81/1.htm">工作流</a> <div>      当我们的流程引擎进入IRC阶段的时候,当循环反馈模型出现之后,每次循环都会导致一大堆节点内存数据残留在系统内存中,循环的次数越多,这些残留数据将导致系统内存溢出,并使得引擎崩溃。。。。。。       而解决办法就是利用汇编语言或者其它系统编程语言,在引擎运行时,把这些残留数据清除掉。</div> </li> <li><a href="/article/2363.htm" title="自定义类的equals函数" target="_blank">自定义类的equals函数</a> <span class="text-muted">dai_lm</span> <a class="tag" taget="_blank" href="/search/equals/1.htm">equals</a> <div>仅作笔记使用 public class VectorQueue { private final Vector<VectorItem> queue; private class VectorItem { private final Object item; private final int quantity; public VectorI</div> </li> <li><a href="/article/2490.htm" title="Linux下安装R语言" target="_blank">Linux下安装R语言</a> <span class="text-muted">datageek</span> <a class="tag" taget="_blank" href="/search/R%E8%AF%AD%E8%A8%80+linux/1.htm">R语言 linux</a> <div>命令如下:sudo gedit  /etc/apt/sources.list1、deb http://mirrors.ustc.edu.cn/CRAN/bin/linux/ubuntu/ precise/ 2、deb http://dk.archive.ubuntu.com/ubuntu hardy universesudo apt-key adv --keyserver ke</div> </li> <li><a href="/article/2617.htm" title="如何修改mysql 并发数(连接数)最大值" target="_blank">如何修改mysql 并发数(连接数)最大值</a> <span class="text-muted">dcj3sjt126com</span> <a class="tag" taget="_blank" href="/search/mysql/1.htm">mysql</a> <div>MySQL的连接数最大值跟MySQL没关系,主要看系统和业务逻辑了   方法一:进入MYSQL安装目录 打开MYSQL配置文件 my.ini 或 my.cnf查找 max_connections=100 修改为 max_connections=1000 服务里重起MYSQL即可   方法二:MySQL的最大连接数默认是100客户端登录:mysql -uusername -ppass</div> </li> <li><a href="/article/2744.htm" title="单一功能原则" target="_blank">单一功能原则</a> <span class="text-muted">dcj3sjt126com</span> <a class="tag" taget="_blank" href="/search/%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E7%9A%84%E7%A8%8B%E5%BA%8F%E8%AE%BE%E8%AE%A1/1.htm">面向对象的程序设计</a><a class="tag" taget="_blank" href="/search/%E8%BD%AF%E4%BB%B6%E8%AE%BE%E8%AE%A1/1.htm">软件设计</a><a class="tag" taget="_blank" href="/search/%E7%BC%96%E7%A8%8B%E5%8E%9F%E5%88%99/1.htm">编程原则</a> <div>单一功能原则[ 编辑]     SOLID 原则 单一功能原则 开闭原则 Liskov代换原则 接口隔离原则 依赖反转原则 查   论   编 在面向对象编程领域中,单一功能原则(Single responsibility principle)规定每个类都应该有</div> </li> <li><a href="/article/2871.htm" title="POJO、VO和JavaBean区别和联系" target="_blank">POJO、VO和JavaBean区别和联系</a> <span class="text-muted">fanmingxing</span> <a class="tag" taget="_blank" href="/search/VO/1.htm">VO</a><a class="tag" taget="_blank" href="/search/POJO/1.htm">POJO</a><a class="tag" taget="_blank" href="/search/javabean/1.htm">javabean</a> <div>POJO和JavaBean是我们常见的两个关键字,一般容易混淆,POJO全称是Plain Ordinary Java Object / Plain Old Java Object,中文可以翻译成:普通Java类,具有一部分getter/setter方法的那种类就可以称作POJO,但是JavaBean则比POJO复杂很多,JavaBean是一种组件技术,就好像你做了一个扳子,而这个扳子会在很多地方被</div> </li> <li><a href="/article/2998.htm" title="SpringSecurity3.X--LDAP:AD配置" target="_blank">SpringSecurity3.X--LDAP:AD配置</a> <span class="text-muted">hanqunfeng</span> <a class="tag" taget="_blank" href="/search/SpringSecurity/1.htm">SpringSecurity</a> <div>前面介绍过基于本地数据库验证的方式,参考http://hanqunfeng.iteye.com/blog/1155226,这里说一下如何修改为使用AD进行身份验证【只对用户名和密码进行验证,权限依旧存储在本地数据库中】。   将配置文件中的如下部分删除: <!-- 认证管理器,使用自定义的UserDetailsService,并对密码采用md5加密--> </div> </li> <li><a href="/article/3125.htm" title="mac mysql 修改密码" target="_blank">mac mysql 修改密码</a> <span class="text-muted">IXHONG</span> <a class="tag" taget="_blank" href="/search/mysql/1.htm">mysql</a> <div>$ sudo /usr/local/mysql/bin/mysqld_safe –user=root & //启动MySQL(也可以通过偏好设置面板来启动)$ sudo /usr/local/mysql/bin/mysqladmin -uroot password yourpassword //设置MySQL密码(注意,这是第一次MySQL密码为空的时候的设置命令,如果是修改密码,还需在-</div> </li> <li><a href="/article/3252.htm" title="设计模式--抽象工厂模式" target="_blank">设计模式--抽象工厂模式</a> <span class="text-muted">kerryg</span> <a class="tag" taget="_blank" href="/search/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/1.htm">设计模式</a> <div>抽象工厂模式:     工厂模式有一个问题就是,类的创建依赖于工厂类,也就是说,如果想要拓展程序,必须对工厂类进行修改,这违背了闭包原则。我们采用抽象工厂模式,创建多个工厂类,这样一旦需要增加新的功能,直接增加新的工厂类就可以了,不需要修改之前的代码。     总结:这个模式的好处就是,如果想增加一个功能,就需要做一个实现类,</div> </li> <li><a href="/article/3379.htm" title="评"高中女生军训期跳楼”" target="_blank">评"高中女生军训期跳楼”</a> <span class="text-muted">nannan408</span> <div>   首先,先抛出我的观点,各位看官少点砖头。那就是,中国的差异化教育必须做起来。    孔圣人有云:有教无类。不同类型的人,都应该有对应的教育方法。目前中国的一体化教育,不知道已经扼杀了多少创造性人才。我们出不了爱迪生,出不了爱因斯坦,很大原因,是我们的培养思路错了,我们是第一要“顺从”。如果不顺从,我们的学校,就会用各种方法,罚站,罚写作业,各种罚。军</div> </li> <li><a href="/article/3506.htm" title="scala如何读取和写入文件内容?" target="_blank">scala如何读取和写入文件内容?</a> <span class="text-muted">qindongliang1922</span> <a class="tag" taget="_blank" href="/search/java/1.htm">java</a><a class="tag" taget="_blank" href="/search/jvm/1.htm">jvm</a><a class="tag" taget="_blank" href="/search/scala/1.htm">scala</a> <div>直接看如下代码: package file import java.io.RandomAccessFile import java.nio.charset.Charset import scala.io.Source import scala.reflect.io.{File, Path} /** * Created by qindongliang on 2015/</div> </li> <li><a href="/article/3633.htm" title="C语言算法之百元买百鸡" target="_blank">C语言算法之百元买百鸡</a> <span class="text-muted">qiufeihu</span> <a class="tag" taget="_blank" href="/search/c/1.htm">c</a><a class="tag" taget="_blank" href="/search/%E7%AE%97%E6%B3%95/1.htm">算法</a> <div>中国古代数学家张丘建在他的《算经》中提出了一个著名的“百钱买百鸡问题”,鸡翁一,值钱五,鸡母一,值钱三,鸡雏三,值钱一,百钱买百鸡,问翁,母,雏各几何? 代码如下: #include <stdio.h> int main() { int cock,hen,chick; /*定义变量为基本整型*/ for(coc</div> </li> <li><a href="/article/3760.htm" title="Hadoop集群安全性:Hadoop中Namenode单点故障的解决方案及详细介绍AvatarNode" target="_blank">Hadoop集群安全性:Hadoop中Namenode单点故障的解决方案及详细介绍AvatarNode</a> <span class="text-muted">wyz2009107220</span> <a class="tag" taget="_blank" href="/search/NameNode/1.htm">NameNode</a> <div>正如大家所知,NameNode在Hadoop系统中存在单点故障问题,这个对于标榜高可用性的Hadoop来说一直是个软肋。本文讨论一下为了解决这个问题而存在的几个solution。 1. Secondary NameNode 原理:Secondary NN会定期的从NN中读取editlog,与自己存储的Image进行合并形成新的metadata image 优点:Hadoop较早的版本都自带,</div> </li> </ul> </div> </div> </div> <div> <div class="container"> <div class="indexes"> <strong>按字母分类:</strong> <a href="/tags/A/1.htm" target="_blank">A</a><a href="/tags/B/1.htm" target="_blank">B</a><a href="/tags/C/1.htm" target="_blank">C</a><a href="/tags/D/1.htm" target="_blank">D</a><a href="/tags/E/1.htm" target="_blank">E</a><a href="/tags/F/1.htm" target="_blank">F</a><a href="/tags/G/1.htm" target="_blank">G</a><a href="/tags/H/1.htm" target="_blank">H</a><a href="/tags/I/1.htm" target="_blank">I</a><a href="/tags/J/1.htm" target="_blank">J</a><a href="/tags/K/1.htm" target="_blank">K</a><a href="/tags/L/1.htm" target="_blank">L</a><a href="/tags/M/1.htm" target="_blank">M</a><a href="/tags/N/1.htm" target="_blank">N</a><a href="/tags/O/1.htm" target="_blank">O</a><a href="/tags/P/1.htm" target="_blank">P</a><a href="/tags/Q/1.htm" target="_blank">Q</a><a href="/tags/R/1.htm" target="_blank">R</a><a href="/tags/S/1.htm" target="_blank">S</a><a href="/tags/T/1.htm" target="_blank">T</a><a href="/tags/U/1.htm" target="_blank">U</a><a href="/tags/V/1.htm" target="_blank">V</a><a href="/tags/W/1.htm" target="_blank">W</a><a href="/tags/X/1.htm" target="_blank">X</a><a href="/tags/Y/1.htm" target="_blank">Y</a><a href="/tags/Z/1.htm" target="_blank">Z</a><a href="/tags/0/1.htm" target="_blank">其他</a> </div> </div> </div> <footer id="footer" class="mb30 mt30"> <div class="container"> <div class="footBglm"> <a target="_blank" href="/">首页</a> - <a target="_blank" href="/custom/about.htm">关于我们</a> - <a target="_blank" href="/search/Java/1.htm">站内搜索</a> - <a target="_blank" href="/sitemap.txt">Sitemap</a> - <a target="_blank" href="/custom/delete.htm">侵权投诉</a> </div> <div class="copyright">版权所有 IT知识库 CopyRight © 2000-2050 E-COM-NET.COM , All Rights Reserved. <!-- <a href="https://beian.miit.gov.cn/" rel="nofollow" target="_blank">京ICP备09083238号</a><br>--> </div> </div> </footer> <!-- 代码高亮 --> <script type="text/javascript" src="/static/syntaxhighlighter/scripts/shCore.js"></script> <script type="text/javascript" src="/static/syntaxhighlighter/scripts/shLegacy.js"></script> <script type="text/javascript" src="/static/syntaxhighlighter/scripts/shAutoloader.js"></script> <link type="text/css" rel="stylesheet" href="/static/syntaxhighlighter/styles/shCoreDefault.css"/> <script type="text/javascript" src="/static/syntaxhighlighter/src/my_start_1.js"></script> </body> </html>