您好,欢迎来到个人技术集锦。
搜索
当前位置:首页全栈之路——前端(一):ES6之字符串、正则的扩展

全栈之路——前端(一):ES6之字符串、正则的扩展

个人技术集锦 2025-06-09
导读本文为电子书《ECMAScript 6 入门》:学习笔记 1. 字符串的扩展 ES6加强了对字符的Unicode表示法支持,原本\uxxxx表示一个字符的形式只能表示四位,也就是\u0000到\uFFFF之间的字符,这个范围之外必须采用双字节。ES6进行了改进之后只要使用大括号括住码点就可以正确解读字符。 "\uD842\uDFB7" // "?" "\u20BB7" // 因为\u20BB无法表示所以结果为" 7" "\u{20BB7}" // "?" "\u{41}\u{42}\u{4

本文为电子书《ECMAScript 6 入门》:学习笔记

1. 字符串的扩展

ES6加强了对字符的Unicode表示法支持,原本\uxxxx表示一个字符的形式只能表示四位,也就是\u0000到\uFFFF之间的字符,这个范围之外必须采用双字节。ES6进行了改进之后只要使用大括号括住码点就可以正确解读字符。

"\uD842\uDFB7"
// "?"

"\u20BB7"
// 因为\u20BB无法表示所以结果为" 7"

"\u{20BB7}"
// "?"

"\u{41}\u{42}\u{43}"
// 相当于\u0041 "ABC"

let hello = 123;
hell\u{6F} // 123

'\u{1F680}' === '\uD83D\uDE80'
// true

ES6位字符串增加了Iterator接口,但for循环无法正确识别,for…of则会正确识别出来这是一个字符:

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);
}
// "?"

JS规定,以下五个字符不能在字符串中直接使用:
U+005C:反斜杠(reverse solidus)
U+000D:回车(carriage return)
U+2028:行分隔符(line separator)
U+2029:段分隔符(paragraph separator)
U+000A:换行符(line feed)
但是其中的U+2028和U+2029是允许在JSON格式中存在的,所以服务器传输的JSON有可能包含这两个字符导致解析报错。
为了解决这个报错,ES2019允许了字符串直接输入这两个字符。

UTF-8规定0xD800到0xDFFF之间的码点不能单独使用,必须配对使用,但是JSON.stringify()方法可能返回该范围内的单个码点,因此ES2019做了优化,会返回转义字符串留给业务代码自己处理:

JSON.stringify('\u{D834}') // ""\\uD834""
JSON.stringify('\uDF06\uD834') // ""\\udf06\\ud834""

ES6中引入了模版字符串:

// 普通字符串
`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 x = 1;
let y = 2;

`${x} + ${y} = ${x + y}`
// "1 + 2 = 3"

`${x} + ${y * 2} = ${x + y * 2}`
// "1 + 4 = 5"

let obj = {x: 1, y: 2};
`${obj.x + obj.y}`
// "3"

// 调用函数
function fn() {
  return "Hello World";
}

`foo ${fn()} bar`

2. 正则的扩展

var regex = new RegExp('xyz', 'i');
// 等价于
var regex = /xyz/i;

var regex = new RegExp(/xyz/i);
// 等价于
var regex = /xyz/i;

// ES5中报错
var regex = new RegExp(/xyz/, 'i');
// Uncaught TypeError: Cannot supply flags when constructing one RegExp from another

//ES6中优先函数参数
new RegExp(/abc/ig, 'i').flags
// "i"

ES6 出现之前,字符串对象共有 4 个方法,可以使用正则表达式:match()、replace()、search()和split()。
ES6 将这 4 个方法,在语言内部全部调用RegExp的实例方法,从而做到所有与正则相关的方法,全都定义在RegExp对象上。
String.prototype.match 调用 RegExp.prototype[Symbol.match]
String.prototype.replace 调用 RegExp.prototype[Symbol.replace]
String.prototype.search 调用 RegExp.prototype[Symbol.search]
String.prototype.split 调用 RegExp.prototype[Symbol.split]

ES6新增了u修饰符,用来处理大于\uFFFF的字符,ES5不支持四个字节的UTF-16编码,因此下面一行代码会将其识别为两个字符,导致判断为true。

/^\uD83D/u.test('\uD83D\uDC2A') // false
/^\uD83D/.test('\uD83D\uDC2A') // true

u修饰符还可以用来帮助.字符的识别:

var s = '?';

/^.$/.test(s) // false
/^.$/u.test(s) // true

大括号表示Unicode字符时如果不加上u修饰符会被解读为量词,匹配61个连续的u。

/\u{61}/.test('a') // false
/\u{61}/u.test('a') // true
/\u{20BB7}/u.test('?') // true

有些 Unicode 字符的编码不同,但是字型很相近,比如,\u004B与\u212A都是大写的K。

/[a-z]/i.test('\u212A') // false
/[a-z]/iu.test('\u212A') // true

上面代码中,不加u修饰符,就无法识别非规范的K字符。
没有u修饰符的情况下,正则中没有定义的转义(如逗号的转义,)无效,而在u模式会报错。

/\,/ // /\,/
/\,/u // 报错

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

const r1 = /hello/;
const r2 = /hello/u;

r1.unicode // false
r2.unicode // true

ES6新增了y修饰符,作用与g修饰符类似,也是全局匹配,后一次匹配都从上一次匹配成功的下一个位置开始。不同之处在于,g修饰符只要剩余位置中存在匹配就可,而y修饰符确保匹配必须从剩余的第一个位置开始,这也就是“粘连”的涵义。

var s = 'aaa_aa_a';
var r1 = /a+/g;
var r2 = /a+/y;

r1.exec(s) // ["aaa"]
r2.exec(s) // ["aaa"]

r1.exec(s) // ["aa"]
r2.exec(s) // null

ES6新增了flags属性,可以得到正则表达式的修饰符:

// ES5 的 source 属性
// 返回正则表达式的正文
/abc/ig.source
// "abc"

// ES6 的 flags 属性
// 返回正则表达式的修饰符
/abc/ig.flags
// 'gi'

ES6引入了s修饰符,使.可以匹配包括
U+000A 换行符(\n)
U+000D 回车符(\r)
U+2028 行分隔符(line separator)
U+2029 段分隔符(paragraph separator)
在内的四个行终止符,这就是dotAll模式,因此也在正则表达式中引入了dotAll属性:

/foo.bar/.test('foo\nbar')
// false

/foo[^]bar/.test('foo\nbar')
// true

/foo.bar/s.test('foo\nbar') // true

const re = /foo.bar/s;
// 另一种写法
// const re = new RegExp('foo.bar', 's');

re.test('foo\nbar') // true
re.dotAll // true
re.flags // 's'

/s修饰符和多行修饰符/m不冲突,两者一起使用的情况下,.匹配所有字符,而^和$匹配每一行的行首和行尾。
. 除换行符外的任意字符 ❌ fooXbar
[\s\S] 任意字符(含换行符) ✅ foo\nbar 空格和非空格
[\d\D] 任意字符(含换行符) ✅ foo\nbar 数字和非数字
[^] 任意字符(含换行符) ✅ foo\nbar

ES2018引入了Unicode属性类,功能十分强大,可以进行希腊文字母、罗马数字等的匹配;引入了v修饰符实现Unicode属性类的运算;
引入了具名组匹配,使用exec方法就可以将圆括号中的匹配结果提取出来,但是只能用数字序号饮用,引入具名组匹配后可以指定名字,进而可以。
这里我们不细讲,请教前辈得知,正则表达式的使用场景比较极端,如果是需要写正则表达式的相关库的场景会猛猛写,写完之后调库就好了,现在时间有点紧,打算用到之后再进行系统学习,就这样。

Copyright © 2019- zgxue.com 版权所有 京ICP备2021021884号-5

违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务