一,字符串的扩展
一,字符的 Unicode 表示法
允许采用\uxxxx形式表示一个字符,其中xxxx表示字符的 Unicode 码点。但是只限于码点在\u0000~\uFFFF之间的字符。超出这个范围的字符,必须用两个双字节的形式表示。解决办法:只要将码点放入大括号,就能正确解读该字符。
"\u{20BB7}"
"\u{41}\u{42}\u{43}"
let hello
= 123;
hell\u
{6F}
'\u{1F680}' === '\uD83D\uDE80'
因此,表示一个字符有六种方法了
'\z' === 'z'
'\172' === 'z'
'\x7A' === 'z'
'\u007A' === 'z'
'\u{7A}' === 'z'
二,字符串的遍历器接口
遍历字符串
for (let codePoint of
'foo') {
console
.log(codePoint
)
}
优点是可以识别大于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'
5个字符,不能在字符串里面直接使用,只能使用转义形式。 U+005C:反斜杠 U+000D:回车 U+2028:行分隔符 U+2029:段分隔符 U+000A:换行符 例如:反斜杠,一定要转义写成\\或者\u005c。
四,JSON.stringify() 的改造
如果遇到0xD800到0xDFFF之间的单个码点,或者不存在的配对形式,它会返回转义字符串,留给应用自己决定下一步的处理。
JSON
.stringify('\u{D834}')
JSON
.stringify('\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方法消除它。
模板字符串中嵌入变量,需要将变量名写在${}之中。
throw new Error(
`User $
{user
.name
} is not authorized to
do $
{action
}.`
);
大括号内部可以放入任意的 JavaScript 表达式,可以进行运算,以及引用对象属性。模板字符串之中还能调用函数
function
fn() {
return "Hello World";
}
`foo $
{fn()} bar`
模板字符串中的变量没有声明,将报错。
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
let parse
= eval(compile(template
));
div
.innerHTML
= parse({ supplies
: [ "broom", "mop", "cleaner" ] });
七,标签模板
标签模板其实不是模板,而是函数调用的一种特殊形式。“标签”指的就是函数,紧跟在后面的模板字符串就是它的参数。如果模板字符里面有变量,会将模板字符串先处理成多个参数,再调用函数。
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
}`
;
“标签模板”的一个重要应用,就是过滤 HTML 字符串,防止用户输入恶意内容。多语言转换(国际化处理)。
i18n`Welcome to $
{siteName
}, you are visitor number $
{visitorNumber
}!`
raw属性
tag`First line\nSecond line`
function
tag(strings
) {
console
.log(strings
.raw
[0]);
}
二,正则表达式的扩展
一,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
二,字符串的正则方法
match() 方法可在字符串内检索指定的值,或找到一个或多个正则表达式的匹配
let str
="1 plus 2 equal 3"
str
.match(/\d
+/g
)
replace() 方法用于在字符串中用一些字符替换另一些字符,或替换一个与正则表达式匹配的子串
let str
= 'nihao Jack'
str
.replace(/Jack
/, 'Lucy')
search() 方法用于检索字符串中指定的子字符串,或检索与正则表达式相匹配的子字符串
let str
= 'good body'
str
.search(/body
/)
let str
= 'good body'
str
.search(/girl
/)
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
)
/^.$
/u
.test(s
)
Unicode 字符表示法 必须加上u修饰符,才能识别当中的大括号,否则会被解读为量词。
/\u
{61}/.test('a')
/\u
{61}/u
.test('a')
/\u
{20BB7
}/u
.test('𠮷')
转义 没有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
)
reg2
.exec(s
)
reg1
.exec(s
)
reg2
.exec(s
)
lastIndex属性可以指定每次搜索的开始位置
reg2
.lastsIndex
= 1
reg2
.exec(s
)
实际上y修饰符号隐含了头部匹配的标志
^
单单一个y修饰符对match方法,只能返回第一个匹配,必须与g修饰符联用,才能返回所有匹配。
'a1a2a3'.match(/a\d
/y
)
'a1a2a3'.match(/a\d
/gy
)
六,RegExp.prototype.sticky 属性
表示是否设置了y修饰符
var r
= /hello\d
/y
;
r
.sticky
七,RegExp.prototype.flags 属性
会返回正则表达式的修饰符。
八,s 修饰符:dotAll 模式
引入s修饰符,使得.可以匹配任意单个字符。
/foo
.bar
/.test('foo\nbar')
/foo
.bar
/s
.test('foo\nbar')
这被称为dotAll模式,即点(dot)代表一切字符。所以,正则表达式还引入了一个dotAll属性,返回一个布尔值,表示该正则表达式是否处在dotAll模式。
九,后行断言
“先行断言”:x只有在y前面才匹配,必须写成/x(?=y)/。比如,只匹配百分号之前的数字,要写成/\d+(?=%)/。
/\d
+(?=%)/.exec('100% of US presidents have been male')
“先行否定断言”:x只有不在y前面才匹配,必须写成/x(?!y)/。比如,只匹配不在百分号之前的数字,要写成/\d+(?!%)/
/\d
+(?!%)/.exec('that’s all 44 of them')
“后行断言”正好与“先行断言”相反,/(?<=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];
const month
= matchObj
[2];
const day
= matchObj
[3];
问题: 只能用数字序号引用,组的顺序改变,引用的时候就必须修改序号
具名组匹配,允许为每一个组匹配指定一个名字,既便于阅读代码,又便于引用
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'}