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, "&amp;")
            .replace(/</g, "&lt;")
            .replace(/>/g, "&gt;");

    // Don't escape special characters in the template.
    s += templateData[i];
  }
  return s;
}

 

但是,如果模板字符里面有变量,就不是简单的调用了,而是会将模板字符串先处理成多个参数,再调用函数。

标签模板里面,可以内嵌其他语言。但是,模板字符串默认会将字符串转义,因此导致了无法嵌入其他语言。

 

posted @ 2016-12-26 06:28  Jacob_乔  阅读(168)  评论(0编辑  收藏  举报