es6---字符串的扩展,正则表达式扩展

    科技2023-12-31  74

    一,字符串的扩展

    一,字符的 Unicode 表示法

    允许采用\uxxxx形式表示一个字符,其中xxxx表示字符的 Unicode 码点。但是只限于码点在\u0000~\uFFFF之间的字符。超出这个范围的字符,必须用两个双字节的形式表示。解决办法:只要将码点放入大括号,就能正确解读该字符。 "\u{20BB7}" // "𠮷" "\u{41}\u{42}\u{43}" // "ABC" let hello = 123; hell\u{6F} // 123 '\u{1F680}' === '\uD83D\uDE80' // true 因此,表示一个字符有六种方法了 '\z' === 'z' // true '\172' === 'z' // true '\x7A' === 'z' // true '\u007A' === 'z' // true '\u{7A}' === 'z' // true

    二,字符串的遍历器接口

    遍历字符串 for (let codePoint of 'foo') { console.log(codePoint) } // "f" // "o" // "o" 优点是可以识别大于0xFFFF的码点,传统的for循环无法识别这样的码点。 let text = String.fromCodePoint(0x20BB7); for (let i = 0; i < text.length; i++) { console.log(text[i]); } // " " // " " for (let i of text) { console.log(i); } // "𠮷"

    三,直接输入 U+2028 和 U+2029

    JavaScript 字符串允许直接输入字符,以及输入字符的转义形式 '中' === '\u4e2d' // true 5个字符,不能在字符串里面直接使用,只能使用转义形式。 U+005C:反斜杠 U+000D:回车 U+2028:行分隔符 U+2029:段分隔符 U+000A:换行符 例如:反斜杠,一定要转义写成\\或者\u005c。

    四,JSON.stringify() 的改造

    如果遇到0xD800到0xDFFF之间的单个码点,或者不存在的配对形式,它会返回转义字符串,留给应用自己决定下一步的处理。 JSON.stringify('\u{D834}') // ""\\uD834"" JSON.stringify('\uDF06\uD834') // ""\\udf06\\ud834""

    五,模板字符串

    模板字符串是增强版的字符串,用反引号(`)标识。它可以当作普通字符串使用,也可以用来定义多行字符串,或者在字符串中嵌入变量。 // 普通字符串 `In JavaScript '\n' is a line-feed.` // 多行字符串 `In JavaScript this is not legal.` console.log(`string text line 1 string text line 2`); // 字符串中嵌入变量 let name = "Bob", time = "today"; `Hello ${name}, how are you ${time}?` 在模板字符串中需要使用反引号,则前面要用反斜杠转义。 let greeting = `\`Yo\` World!`; 使用模板字符串表示多行字符串,所有的空格和缩进都会被保留在输出之中。 $('#list').html(` <ul> <li>first</li> <li>second</li> </ul> `//.trim());

    不想要这个换行,可以使用trim方法消除它。

    模板字符串中嵌入变量,需要将变量名写在${}之中。 throw new Error( // 传统写法为 // 'User ' // + user.name // + ' is not authorized to do ' // + action // + '.' `User ${user.name} is not authorized to do ${action}.`); 大括号内部可以放入任意的 JavaScript 表达式,可以进行运算,以及引用对象属性。模板字符串之中还能调用函数 function fn() { return "Hello World"; } `foo ${fn()} bar` // foo Hello World bar 模板字符串中的变量没有声明,将报错。 // 变量place没有声明 let msg = `Hello, ${place}`; // 报错

    六,实例:模板编译

    let template = ` <ul> <% for(let i=0; i < data.supplies.length; i++) { %> <li><%= data.supplies[i] %></li> <% } %> </ul> `;

    使用<%...%>放置 JavaScript 代码,使用<%= ... %>输出 JavaScript 表达式。

    怎么编译这个模板字符串

    使用正则表达式将其转换为 JavaScript 表达式字符串然后将template封装在一个函数里面返回将上面的内容拼装成一个模板编译函数compile //compile函数用法 let parse = eval(compile(template)); div.innerHTML = parse({ supplies: [ "broom", "mop", "cleaner" ] }); // <ul> // <li>broom</li> // <li>mop</li> // <li>cleaner</li> // </ul>

    七,标签模板

    标签模板其实不是模板,而是函数调用的一种特殊形式。“标签”指的就是函数,紧跟在后面的模板字符串就是它的参数。如果模板字符里面有变量,会将模板字符串先处理成多个参数,再调用函数。 let a = 5; let b = 10; tag`Hello ${ a + b } world ${ a * b }`; // 等同于 tag(['Hello ', ' world ', ''], 15, 50);

    tag,它是一个函数。整个表达式的返回值,就是tag函数处理模板字符串后的返回值。 tag函数所有参数的实际值如下。 第一个参数:

    ['Hello ', ' world ', ' ']

    二个参数: 15 第三个参数:50

    let a = 5; let b = 10; function tag(s, v1, v2) { console.log(s[0]); console.log(s[1]); console.log(s[2]); console.log(v1); console.log(v2); return "OK"; } tag`Hello ${ a + b } world ${ a * b}`; // "Hello " // " world " // "" // 15 // 50 // "OK" “标签模板”的一个重要应用,就是过滤 HTML 字符串,防止用户输入恶意内容。多语言转换(国际化处理)。 i18n`Welcome to ${siteName}, you are visitor number ${visitorNumber}!` // "欢迎访问xxx,您是第xxxx位访问者!" raw属性 tag`First line\nSecond line` function tag(strings) { console.log(strings.raw[0]); // strings.raw[0] 为 "First line\\nSecond line" // 打印输出 "First line\nSecond line" }

    二,正则表达式的扩展

    一,RegExp构造函数

    ES5中有两种情况 let regex = new RegExp('xyz', 'i') // 等价于 let regex = /xyz/i let regex = new RegExp(/xyz/i) // 等价于 let regex = /xyz/i

    注意!!!

    let regex = new RegExp(/xyz/, 'i') // 这种写法是错误的 ES6的改变 new RegExp(/abc/ig, 'i').flags // 第二个参数i会将前面的ig进行覆盖

    二,字符串的正则方法

    match() 方法可在字符串内检索指定的值,或找到一个或多个正则表达式的匹配 let str="1 plus 2 equal 3" str.match(/\d+/g) // ['1','2','3'] replace() 方法用于在字符串中用一些字符替换另一些字符,或替换一个与正则表达式匹配的子串 let str = 'nihao Jack' str.replace(/Jack/, 'Lucy') // nihao Lucy search() 方法用于检索字符串中指定的子字符串,或检索与正则表达式相匹配的子字符串 let str = 'good body' str.search(/body/) // 5 let str = 'good body' str.search(/girl/) // -1 split() 方法用于把一个字符串分割成字符串数组 let str = 'good body' str.split('o') ["g", "", "d b", "dy"]

    三,u修饰符

    含义为“Unicode 模式”,用来正确处理大于\uFFFF的 Unicode 字符。也就是说,会正确处理四个字节的 UTF-16 编码。。对于码点大于0xFFFF的 Unicode 字符,点字符不能识别,必须加上u修饰符。 var s = '𠮷'; /^.$/.test(s) // false /^.$/u.test(s) // true Unicode 字符表示法 必须加上u修饰符,才能识别当中的大括号,否则会被解读为量词。 /\u{61}/.test('a') // false /\u{61}/u.test('a') // true /\u{20BB7}/u.test('𠮷') // true 转义 没有u修饰符的情况下,正则中没有定义的转义(如逗号的转义,)无效,而在u模式会报错。 /\,/ // /\,/ /\,/u // 报错

    四,RegExp.prototype.unicode 属性

    正则实例对象新增unicode属性,表示是否设置了u修饰符

    五,y修饰符

    y修饰符,叫做“粘连”(sticky)修饰符。y修饰符的作用与g修饰符类似,也是全局匹配,后一次匹配都从上一次匹配成功的下一个位置开始。不同之处在于,g修饰符只要剩余位置中存在匹配就可,而y修饰符确保匹配必须从剩余的第一个位置开始,这也就是“粘连”的涵义。 let str = 'aaa_aa_a' let reg1 = /a+/g let reg2 = /a+/y reg1.exec(s) // ['aaa'] reg2.exec(s) // ['aaa'] reg1.exec(s) // ['aa'] reg2.exec(s) // null y修饰符从剩余项的第一个位置开始(即_)所以找不到 lastIndex属性可以指定每次搜索的开始位置 reg2.lastsIndex = 1 reg2.exec(s) // ['aa'] 实际上y修饰符号隐含了头部匹配的标志^ 单单一个y修饰符对match方法,只能返回第一个匹配,必须与g修饰符联用,才能返回所有匹配。 'a1a2a3'.match(/a\d/y) // ['a1'] 'a1a2a3'.match(/a\d/gy) // ['a1','a2','a3']

    六,RegExp.prototype.sticky 属性

    表示是否设置了y修饰符

    var r = /hello\d/y; r.sticky // true

    七,RegExp.prototype.flags 属性

    会返回正则表达式的修饰符。

    八,s 修饰符:dotAll 模式

    引入s修饰符,使得.可以匹配任意单个字符。 /foo.bar/.test('foo\nbar') // false 因为.和\n不匹配 /foo.bar/s.test('foo\nbar') // true

    这被称为dotAll模式,即点(dot)代表一切字符。所以,正则表达式还引入了一个dotAll属性,返回一个布尔值,表示该正则表达式是否处在dotAll模式。

    九,后行断言

    “先行断言”:x只有在y前面才匹配,必须写成/x(?=y)/。比如,只匹配百分号之前的数字,要写成/\d+(?=%)/。 /\d+(?=%)/.exec('100% of US presidents have been male') // ["100"] “先行否定断言”:x只有不在y前面才匹配,必须写成/x(?!y)/。比如,只匹配不在百分号之前的数字,要写成/\d+(?!%)/ /\d+(?!%)/.exec('that’s all 44 of them') // ["44"] “后行断言”正好与“先行断言”相反,/(?<=y)x/,/(?<!y)x/

    十,Unicode 属性类

    ES2018 引入了一种新的类的写法\p{...}和\P{...},允许正则表达式匹配符合 Unicode 某种属性的所有字符。\P{…}是\p{…}的反向匹配,即匹配不满足条件的字符。

    十一,具名组匹配

    正则表达式使用圆括号进行组匹配 const REG = /(\d{4})-(\d{2})-(\d{2})/ const matchObj = REG.exec('1999-12-31') const year = matchObj[1]; // 1999 const month = matchObj[2]; // 12 const day = matchObj[3]; // 31 问题: 只能用数字序号引用,组的顺序改变,引用的时候就必须修改序号 具名组匹配,允许为每一个组匹配指定一个名字,既便于阅读代码,又便于引用 const REG = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/ const matchObj = REG.exec('1999-12-31') const year = matchObj.groups.year // 1999 const month = matchObj.groups.month // 12 const day = matchObj.groups.day // 31 如果具名组没有匹配,那么对应的groups对象属性会是undefined

    十二,解构赋值和替换

    有了具名组匹配以后,可以使用解构赋值直接从匹配结果上为变量赋值

    let {groups: {one, two}} = /^(?<one>.*):(?<two>.*)$/u.exec('foo:bar') console.log({one, two}) // {one: 'foo', two: 'bar'}
    Processed: 0.016, SQL: 8