JavaScript学习笔记--ES6学习(四) 字符串的扩展
ES6对字符串进行了一些扩展,主要表现在对Unicode 大于\uFFFF的字符的处理上。
1. ES6中字符的Unicode表示方法
在ES5中,字符串的Unicode表示方法: \uxxxx 。 xxxx表示字符的码点,这种表示仅限于\u0000 到 \uFFFF 之间的字符,超出的需要用双字节来表示。
在ES6中,对字符串的Unicode表示方法进行了改进,将码点放入大括号即可:
"\u{20BB7}" // "𠮷" "\u{41}\u{42}\u{43}" // "ABC" let hello = 123; hell\u{6F} // 123 '\u{1F680}' === '\uD83D\uDE80' // true
有了这一种方法之后,JavaScript一共有6种方式可以表示一个字符:
'\z' === 'z' // true '\172' === 'z' // true '\x7A' === 'z' // true '\u007A' === 'z' // true '\u{7A}' === 'z' // true
2.ES6中对码点和字符转换的方法扩展
(1)''.codePointAt() 替代 ''.charCodeAt()
JavaScript内部,字符以UTF-16的格式储存,每个字符固定为
2
个字节。对于那些需要4
个字节储存的字符(Unicode码点大于0xFFFF
的字符),JavaScript会认为它们是两个字符。对于这种
4
个字节的字符,JavaScript不能正确处理,字符串长度会误判为2
,而且charAt
方法无法读取整个字符,charCodeAt
方法只能分别返回前两个字节和后两个字节的值。ES6提供了
codePointAt
方法,能够正确处理4个字节储存的字符,返回一个字符的码点 :var s = '𠮷a'; s.codePointAt(0) // 134071 s.codePointAt(1) // 57271 s.codePointAt(2) // 97
codePointAt
方法返回的是码点的十进制值,如果想要十六进制的值,可以使用toString
方法转换一下。
在上面的例子中,codePointAt
方法的参数,仍然是不正确的。比如,上面代码中,字符a
在字符串s
的正确位置序号应该是1,但是必须向codePointAt
方法传入2。解决这个问题的一个办法是使用for...of
循环,因为它会正确识别32位的UTF-16字符。codePointAt
方法是测试一个字符由两个字节还是由四个字节组成的最简单方法。(2)String.fromCodePoint() 替代 String.fromCharCode()
对应地,ES6提供了fromCodePoint方法将码点转换为字符。
(3)for...of 替代 for进行循环遍历
ES6为字符串添加了遍历器接口,使得字符串可以被for...of循环遍历,这个遍历器最大的有点事可以识别大于0xFFF的码点,传统的for循环无法识别这样的码点:
var text = String.fromCodePoint(0x20BB7); for (let i = 0; i < text.length; i++) { console.log(text[i]); } // " " // " " for (let i of text) { console.log(i); } // "𠮷"
(4)其他有用的方法扩展
normolize() 处理欧洲语言音调字母码点转换。
indcludes() 返回布尔值,表示是否找到了参数字符串。
startsWith() 返回布尔值,参数字符串是否字源字符串的头部
endsWith() 返回布尔值,参数字符串是否在源字符串的尾部
var s = 'Hello world!'; s.startsWith('Hello') // true s.endsWith('!') // true s.includes('o') // true
这三个方法都支持第二个参数,用来标明起始位置。
var s = 'Hello world!'; s.startsWith('world', 6) // true s.endsWith('Hello', 5) // true s.includes('Hello', 6) // false
repeat(n) 返回一个字符串,将源字符串重复n次
'x'.repeat(3) // "xxx" 'hello'.repeat(2) // "hellohello" 'na'.repeat(0) // ""
padStart() padEnd()补全字符串长度
'x'.padStart(5, 'ab') // 'ababx' 'x'.padStart(4, 'ab') // 'abax' 'x'.padEnd(5, 'ab') // 'xabab' 'x'.padEnd(4, 'ab') // 'xaba'
(5)模板字符串
模板字符串是增强版的字符串,使用反引号(`)进行标识, 它可以当作普通字符串使用,也可以用来定义多行字符串,或者在字符串中嵌入变量。 如果使用模板字符串表示多行字符串,所有的空格和缩进都会被保留在输出之中。
// 普通字符串 `In JavaScript '\n' is a line-feed.` // 多行字符串 `In JavaScript this is not legal.` console.log(`string text line 1 string text line 2`); // 字符串中嵌入变量 var name = "Bob", time = "today"; `Hello ${name}, how are you ${time}?`
模板字符串可以紧跟在一个函数名后面,该函数将被调用来处理这个模板字符串。这被称为“标签模板”功能(tagged template)。
alert`123` // 等同于 alert(123)
“标签模板”的一个重要应用,就是过滤HTML字符串,防止用户输入恶意内容。
var message = SaferHTML`<p>${sender} has sent you a message.</p>`; function SaferHTML(templateData) { var s = templateData[0]; for (var i = 1; i < arguments.length; i++) { var arg = String(arguments[i]); // Escape special characters in the substitution. s += arg.replace(/&/g, "&") .replace(/</g, "<") .replace(/>/g, ">"); // Don't escape special characters in the template. s += templateData[i]; } return s; }
但是,如果模板字符里面有变量,就不是简单的调用了,而是会将模板字符串先处理成多个参数,再调用函数。
标签模板里面,可以内嵌其他语言。但是,模板字符串默认会将字符串转义,因此导致了无法嵌入其他语言。