ES6笔记 - 字符串的扩展

现在ES6有着广泛的应用,ES6对ES5有着大量的语法更新和改动,掌握ES6相关特性是前端的必要技能,有利于学习掌握新的知识,提升编码效率和质量。

更好的Unicode编码支持

ES6中新增 String.prototype.codePointAt(); String.fromCharCode();两个函数, 来分别获取32位表示的字符码点,和根据32位表示的字符码点来解析成字符。

JavaScript内部,字符以UTF-16的格式储存,每个字符固定为2个字节。
字符可以使用Unicode编码 \u0000——\uFFFF 之间的字符来表示,超出这个范围的使用两个Unicode编码表示 “𠮷”: \uD842\uDFB7
Unicode编码\uxxxx 其中 xxxx表示字符的码点。

大括号表示法 “𠮷” \u{20BB7} === \uD842\uDFB7 这两个字符是完全等价的

在 js 中一个字符通常是用两个字节来表示也就是16位,但有一些特殊字符是用4个字节来存储的,也就是32位,charCodeAt 不能很好的处理32位的字符,ES6提供了codePointAt方法,能够正确处理4个字节储存的字符,返回一个字符的码点。

1个字符 = 2个字节(1个Unicode编码)/4个字节(2个Unicode编码)

'𠮷'.length //2
'枯'.length //1

由于 ‘𠮷’ 由4个字节存储,那么就是2个字符的长度
由于 ‘枯’ 由2个字节存储,那么就是1个字符的长度

'枯'.charCodeAt(0) //26543 => \u67af
'枯'.charCodeAt(1) //NaN

(26543).toString(16) //67af

String.fromCharCode('26543') //"枯"
String.fromCharCode('0x67AF') //"枯"

由1个Unicode编码表示,返回了码点的十进制数26543,转换为16进制为67af,js中16进制表示为 0x67AF
通过ES5的String.fromCharCode()函数可以解析码点为字符

'𠮷'.charCodeAt(0) //55362 => \uD842
'𠮷'.charCodeAt(1) //57271 => \uDFB7

"𠮷".codePointAt(0) //134071
"𠮷".codePointAt(1) //57271

汉字“𠮷”的码点是0x20BB7,UTF-16编码为0xD842 0xDFB7(十进制为55362 57271)
由2个Unicode编码表示,返回了两个码点的十进制数

上面 charCodeAt(0) 返回了’𠮷’字符前两个字节的码点,而 codePointAt(0) 返回了整个字符的码点
也就是说 charCodeAt(0) 无法返回4个字节表示的字符的完整码点
所以 ES6 新增了codePointAt(0)来获取4个字节表示的字符的码点
codePointAt(1)codePointAt(0) 不同,codePointAt(1) 返回的是’𠮷’字符后两个字节的码点,与 charCodeAt(1) 结果一致

对字符串操作的扩展

ES6新增 includes(),startsWith(),endsWith(),repeat() 四个String的扩展函数

  • includes(String, startIndex):是否包含某字符串, 返回值:true/false, 第二个参数:从某个索引开始
  • startsWith(String, startIndex):是否以某字符串开头, 返回值:true/false, 第二个参数:从某个索引开始
  • endsWith(String, startNum):是否以某字符串结尾, 返回值:true/false, 第二个参数:从前n个字符查找
  • repeat(Number):重复某字符串, 返回值:重复过的字符串
var s = 'Hello world!';
s.includes('o w'); //true
s.startsWith('He'); //true
s.startsWith('He', 3); //false
s.endsWith('ld'); //false
s.endsWith('ld',11); //true
s.repeat(3); //"Hello world!Hello world!Hello world!"

ES7新增String.propotype.padStart(length, padStr),String.propotype.padEnd(length, padStr)用于补全字符串

参数:length表示要补全的长度,padStr表示用这个字符串来补全。

var s = 'x';
//不带第二个参数,以空格补全
'x'.padStart(4) // ' x'
'x'.padEnd(4) // 'x '

//补全数字位数
'12'.padStart(10, '0') // "0000000012"
'123456'.padStart(10, '0') // "0000123456"

//生成提示字符格式
'12'.padStart(10, 'YYYY-MM-DD') // "YYYY-MM-12"
'09-12'.padStart(10, 'YYYY-MM-DD') // "YYYY-09-12"

更多字符相关

模板字符串

基本特点

  • 字符串使用反引号(`)包裹,例:`字符串模板内容`
  • 模板内换行和缩进都会保留
  • 可嵌入变量,变量名写在 ${}
  • 变量花括号内可执行任意的JS表达式,运算、引用对象、调用函数
  • 模板可以嵌套使用
//保留空格换行
var tpl1 = `
<ul>
<li>first</li>
<li<second</li>
</ul>
`;

console.log(tpl1)

/*
<ul>
<li>first</li>
<li>second</li>
</ul>
*/

// 引用变量
var x=1, y =2;
console.log(`${x} + ${y*2} = ${x+y*2}`);
// 1 + 4 = 5

// 引用对象
var obj = {x:1, y:2}
console.log(`${obj.x} + ${obj.y}`)
// 1 + 2

// 执行函数
function num(){ return 11 }
console.log(`Number is ${num()}`)
// Number is 11

// 模板嵌套
var tpl2 = names=>`<ul>${names.map(v=>`<li>${v}</li>`)}</ul>`;
undefined
tpl2(['hello','world'])
// "<ul><li>hello</li>,<li>world</li></ul>"

标签模板

将模板本身做为一个函数的参数,这个函数将被用来处理模板中的内容

函数名称后面必紧跟模板内容

var a = 1, b = 2;
var tag = function(arr, ...values){console.log(arr); console.log(...values)};
tag`数字${a}加上${b}等于${a+b}`
// ["数字", "加上", "等于", "", raw: Array[4]]
// 1 2 3

应用:过滤模板中的字符(防止xss)、国际化处理

String.raw()

字符串处理,可用于转义模板中的\

String.raw`Hi\u00a`;
// 'Hi\\u00a'

处理具有raw属性的对象, 且raw的值必须可转换成数组

String.raw({raw:'功不有人'}, '夫','负','心');
// "功夫不负有心人"

//等同于
String.raw({raw:['功','不','有','人']}, '夫','负','心');

Object.is()

用于精确的比较两个对象是否绝对相等

在没有Object.is()出现之前,我们使用 === 来判断两个对象是否相等,但是使用 ===NaNNaN 返回的是 false+0-0 返回的是trueObject.is() 的出现正好弥补这一点

console.log(+0 === -0);             // true
console.log(Object.is(+0, -0)); // false

console.log(NaN === NaN); // false
console.log(Object.is(NaN, NaN)); // true