学习记录--《深入理解ES6》之字符串与正则表达式

正则表达式y标志

在 Firefox 实现了对正则表达式 y 标志的专有扩展之后,ES6 将该实现标准化。 y 标志影
响正则表达式搜索时的粘连( sticky )属性,它表示从正则表达式的 lastIndex 属性值的
位置开始检索字符串中的匹配字符。如果在该位置没有匹配成功,那么正则表达式将停止检
索。为了明白它是如何工作的,考虑如下的代码:

var text = "hello1 hello2 hello3",
    pattern = /hello\d\s?/,
    result = pattern.exec(text),
    globalPattern = /hello\d\s?/g,
    globalResult = globalPattern.exec(text),
    stickyPattern = /hello\d\s?/y,
    stickyResult = stickyPattern.exec(text);
    
console.log(result[0]); // "hello1 "
console.log(globalResult[0]); // "hello1 "
console.log(stickyResult[0]); // "hello1 "

pattern.lastIndex = 1;
globalPattern.lastIndex = 1;
stickyPattern.lastIndex = 1;

result = pattern.exec(text);
globalResult = globalPattern.exec(text);
stickyResult = stickyPattern.exec(text);

console.log(result[0]); // "hello1 "
console.log(globalResult[0]); // "hello2 "
console.log(stickyResult[0]); // Error! stickyResult is null

此例中有三个正则表达式: pattern 中的表达式没有使用任何标志, globalPattern 使用了
g 标志, stickyPattern 则使用了 y 标志。对 console.log() 的第一次调用,三个正则
表达式分别都返回了 "hello1 " ,此字符串尾部有个空格。
此后,三个模式的 lastIndex 属性全部被更改为 1 ,表示三个模式的正则表达式都应当从第
二个字符开始尝试匹配。不使用任何标志的正则表达式完全忽略了对于 lastIndex 的更改,
仍然毫无意外地匹配了 "hello1 " ;而使用 g 标志的正则表达式继续匹配了 "hello2 " ,
因为它从第二个字符( “e” )开始,持续向着字符串尾部方向搜索;粘连的正则表达式则在第二个字符处没有匹配成功,因此 stickyResult 的值是 null 。

复制正则表达式

在ES5中,你可以将正则表达式传递给RegExp构造器来复制它

var re1 = /ab/i,
	  re2 = new RegExp(re1);

re2 变量只是re1的一个副本。但如果你向RegExp构造器传递了第二个参数,即正则表达式的标志,那么该代码就无法工作。

var re1 = /ab/i,
 	// ES5中会抛出错误,ES6中可用
 	 re2 = new RegExp(re1, "g");

如果在ES5环境中运行这段代码,那么你会收到一条错误信息,表示在第一个参数已经是正则表达式的情况下不能再使用第二个参数。ES6则修改了这个行为,允许使用第二个参数,并且让它覆盖第一个参数中的标志。例如:

var re1 = /ab/i,
	 re2 = new RegExp(re1,"g");

console.log(re1.toString());    // "/ab/i"
console.log(re2.toString());	  // "/ab/g"

console.log(re1.test("ab"));  //true
console.log(re2.test("ab")); //true

console.log(re1.test("AB")); //true
console.log(re2.test("AB"));   //false

此代码中的re1 带有忽略大小写的i 标志,而re2则只带有全局的g 标志。RegExp 构造器复制了re1 的模式并用g 标志替代了i 标志。如果没有第二个参数,re2就会拥有与re1相同的标志。

flag属性

ES6 新增了 flags 属性用于配合 source属性,让标志的获取变得更容易。这两个属性均为只有getter的原型访问器属性,因此都是只读的。flags 属性使得检查正则表达式更容易,有助于调试与继承。
加入ES6的flags属性,会返回正则表达式中所有标志组成的字符串形式。例如

var re = /ab/g;
console.log(re.source);
console.log(re.flags);

模板字面量

基本语法

模板字面量的最简单语法,是使用反引号(`)来包裹普通字符串,而不是用双引号或单引号。

let message = `Hello world!`;
console.log(message);  //"Hello world!"
console.log(typeof message); //"string"
console.log(message.length); // 12

此代码说明了message变量包含的是一个普通js字符串。模板字面量语法被用于创建一个字符串值,并被赋值给了message变量。
若你想在字符串中包含反引号,只需使用反斜杠(\)转义即可

let message = `\`Hello\` world!`;
console.log(message);  //"`Hello world!`"
console.log(typeof message); //"string"
console.log(message.length); // 14

在模板字面量中无需对双引号或单引号进行转义。

多行字符串

ES6之前的多行字,JS缺失。
ES6的模板字面量使多行字符串更易创建,因为它不需要特殊的语法。只需在想要的位置包含换行即可,而且它会显示在结果中。

let message = ` Multiline
string`;
console.log(message);  //"Multiline
                                      // string"
 console.log(message.length);   //16     
 //用\n 达到同样的换行效果
 message = ` Multiline\nstring`;           

//反引号之内的所有空白符都是字符串的一部分,因此需要留意缩进。
message = `Multiline
               string`
 console.log(message.length);   //31                            
制造替换位

替换位由起始的**${** 与结束的**}**来界定,中间允许放入任意的JS表达式。最简单的替换位允许你将本地变量直接嵌入到结果字符串中。

let name = "John",
	message = `Hello, ${name}.`;
console.log(message);	//"Hello,John."

替换位${name}会访问本地变量name,并将其值插入到message字符串中。message 变量会立即保留该替换位的结果。

模板字面量能访问到作用域中的任意的可访问变量。试图使用未定义的变量会抛出错误,无论是严格模式还是非严格模式。

既然替换位是JS表达式,那么可替换的就不仅仅是简单的变量名。你可以轻易嵌入计算、函数调用,等等。

let count = 10 ,
	price = 0.25,
	message = `${count} items cost $${(count * price).toFixed(2)}.`;

console.log(message); // "10 items cost $2.50."	

第二个替换位之前的美元符号被照常输出,因为没有左花括号紧随其后。

模板字面量本身也是JS表达式,意味着你可以将模板字面量嵌入到另一个模板字面量内部,如下

let name = "John",	
	message = `hell, ${`my name is ${ name }`}.`;
console.log(message); // "Hello, my name is John."
标签化模板
function passthru(literals, ...substitutions) {
let result = "";
// 仅使用 substitution 的元素数量来进行循环
for (let i = 0; i < substitutions.length; i++) {
result += literals[i];
result += substitutions[i];
}
// 添加最后一个字面量
result += literals[literals.length - 1];
return result;
}
let count = 10,
price = 0.25,
message = passthru`${count} items cost $${(count * price).toFixed(2)}.`;
console.log(message); // "10 items cost $2.50."

本例定义了 passthru 标签,能够执行与模板字面量的默认行为相同的转换操作。唯一的诀窍是在循环中使用 substituions.length 而不是 literals.length 来避免substituions 数组的越界。它能工作是由于 ES6 对 literals 和 substituions 的良好定义。

总结

完整的 Unicode 支持允许 JS 以合理的方式处理 UTF-16 字符。通过 codePointAt() 与
String.fromCodePoint() 在代码点和字符之间转换的能力,是字符串操作的一大进步。正则
表达式新增的 u 标志使得直接操作代码点而不是 16 位字符变为可能,而 normalize() 方
法则允许进行更恰当的字符串比较。

ES6 也添加了操作字符串的新方法,允许你更容易识别子字符串,而不用管它在父字符串中的位置。正则表达式同样引入了许多功能。

模板字面量是 ES6 的一项重要补充,允许你创建领域专用语言( DSL )让字符串的创建更容易。能将变量直接嵌入到模板字面量中,意味着开发者在组合长字符串与变量时,有了一种比字符串拼接更为安全的工具。

内置的多行字符串支持,是普通 JS 字符串绝对无法做到的,这使得模板字面量成为凌驾于前者之上的有用升级。尽管在模板字面量中允许直接使用换行,你依然可以使用 \n 或其它字符转义序列。

模板标签是创建 DSL 最重要的部分。标签是接收模板字面量片段作为参数的函数,你可以使用它们来返回合适的字符串。这些数据包括了字面量、等价的原始值以及替换位的值,标签使用这些信息片段来决定输出。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值