字符串的扩展
字符的Unicode表示法
ES6 加强了对 Unicode 的支持,允许采用
\uxxxx
形式表示一个字符,其中xxxx
表示字符的 Unicode 码点,但是,这种表示法只限于码点在\u0000
~\uFFFF
之间的字符。超出这个范围的字符,必须用两个双字节的形式表示"\uD842\uDFB7" // "𠮷" "\u20BB7" // " 7",超出会按\u20BB+7处理
改进:只要将码点放入大括号,就能正确解读该字符
"\u{20BB7}" // "𠮷"
字符串的遍历器接口
ES6 为字符串添加了遍历器接口(详见《Iterator》一章),使得字符串可以被
for...of
循环遍历for (let codePoint of 'foo') { console.log(codePoint) } // "f" "o" "o"
除了遍历字符串,这个遍历器最大的优点是可以识别大于
0xFFFF
的码点,传统的for
循环无法识别这样的码点let text = String.fromCodePoint(0x20BB7); for (let i = 0; i < text.length; i++) { console.log(text[i]); } // " " " " 字符串text只有一个字符,但是for循环会认为它包含两个字符(都不可打印) for (let i of text) { console.log(i); } // "𠮷" for...of循环会正确识别出这一个字符
模板字符串
模板字符串(template string)是增强版的字符串,用反引号(`)标识。它可以当作普通字符串使用,也可以用来定义多行字符串,或者在字符串中嵌入变量${}
let name = "Bob", time = "today"; `Hello ${name}, how are you ${time}?`
上面代码中的模板字符串,都是用反引号表示。如果在模板字符串中需要使用反引号,则前面要用反斜杠转义
let greeting = `\`Yo\` World!`;
所有模板字符串的空格和换行,都是被保留的,比如
<ul>
标签前面会有一个换行。如果你不想要这个换行,可以使用trim
方法消除它$('#list').html(` <ul> <li>first</li> <li>second</li> </ul> `.trim());
大括号内部可以放入任意的 JavaScript 表达式,可以进行运算,以及引用对象属性,如果大括号中的值不是字符串,将按照一般的规则转为字符串
let x = 1; let y = 2; `${x} + ${y * 2} = ${x + y * 2}` // "1 + 4 = 5" let obj = {x: 1, y: 2}; `${obj.x + obj.y}` // "3"
模板字符串之中还能调用函数
function fn() { return "Hello World"; } `foo ${fn()} bar` // foo Hello World bar
模板字符串还能嵌套
如果需要引用模板字符串本身,在需要时执行,可以写成函数
let func = (name) => `Hello ${name}!`; func('Jack') // "Hello Jack!"
标签模板
- 模板字符串可以紧跟在一个函数名后面,该函数将被调用来处理这个模板字符串。这被称为“标签模板”功能(tagged template)
alert`hello` // 等同于 alert(['hello']); alert('hello');
- 模板字符串里面如果有变量,则先处理成多个参数,再调用函数
let a = 5; let b = 10; tag`Hello ${ a + b } world ${ a * b }`; // 等同于 tag(['Hello ', ' world ', ''], 15, 50); function tag(stringArr, value1, value2){ // ... } // 等同于 function tag(stringArr, ...values){ // ... }
let total = 30; let msg = passthru`The total is ${total} (${total*1.05} with tax)`; function passthru(literals) { let result = ''; let i = 0; while (i < literals.length) { result += literals[i++]; //只会输出字符串,不会输出变量 if (i < arguments.length) { result += arguments[i]; //会输出变量,但是第一个元素是整个字符串的字符区,故跳过第一个部分,再将各个参数按照原来的位置拼合回去 } } return result; } msg // "The total is 30 (31.5 with tax)" //可以优化passthru函数,使用rest参数 function passthru(literals, ...values) { let output = ""; let index; for (index = 0; index < values.length; index++) { output += literals[index] + values[index]; } output += literals[index] return output; }
- 标签模板的一个重要应用,就是过滤 HTML 字符串,防止用户输入恶意内容
let message = SaferHTML`<p>${sender} has sent you a message.</p>`; function SaferHTML(templateData) { let s = templateData[0]; for (let i = 1; i < arguments.length; i++) { let 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; } let sender = '<script>alert("abc")</script>'; // 恶意代码 let message = SaferHTML`<p>${sender} has sent you a message.</p>`; message // <p><script>alert("abc")</script> has sent you a message.</p>