浏览器标题切换
浏览器标题切换end

柒壹零柒

学习笔记|字符串的扩展

1.字符的 Unicode 表示法

es6较早版本支持的码点是用UTF16BE编码(Unicode转换后的程序数据)来编写的,只限于\u0000~\uFFFF,超出这个范围就要用双字节表示,即:

console.log("\u0061")
// a

console.log("\uD842\uDFB7")
// "𠮷"

对于Unicode超出部分并不是很能识别,如果直接在\u后面跟上超过0xFFFF的数值(比如\u20BB7),JavaScript 会理解成\u20BB+7。\u20BB是一个表情符号,后面跟着一个7,如下:

console.log("\u20BB7")
// "₻7"

 ES6 对这一点做出了改进,只要将码点放入大括号,就能正确解读Unicode

console.log("\u{20BB7}"// "𠮷"

console.log("\u{41}\u{42}\u{43}")
// "ABC"

let hello = 123;
hell\u{6F} // 123

'\u{1F680}' === '\uD83D\uDE80'
// true

附上𠮷的各种编码:

Unicode编码:00020BB7
UTF8编码:F0A0AEB7
UTF16BE编码:FEFFD842DFB7
UTF16LE编码:FFFE42D8B7DF
UTF32BE编码:0000FEFF00020BB7
UTF32LE编码:FFFE0000B70B0200
 

2.字符串的遍历

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]);
}
// "�"
// "�"

for (let i of text) {
  console.log(i);
}
// "𠮷"

 上面代码中,字符串text只有一个字符,但是for循环会认为它包含两个字符(都不可打印),而for...of循环会正确识别出这一个字符。

 

3.字符串的转义

JavaScript 规定有5个字符,不能在字符串里面直接使用,只能使用转义形式。

  • U+005C:反斜杠(reverse solidus)
  • U+000D:回车(carriage return)
  • U+2028:行分隔符(line separator)
  • U+2029:段分隔符(paragraph separator)
  • U+000A:换行符(line feed)

举例来说,字符串里面不能直接包含反斜杠,一定要转义写成\\或者\u005c。

 

4.模板字符串

传统的 JavaScript 语言,字符串模板通常是

let num = 2
"111"+num+"1"
//"11121"

这样的写法比较繁琐,ES6 引入了模板字符串解决这个问题。

let num = 2

`111${num}1`
//"11121"

模板字符串(template string)是增强版的字符串,用反引号(`)标识。它可以当作普通字符串使用,也可以用来定义多行字符串,或者在字符串中嵌入变量(模板字符串中嵌入变量,需要将变量名写在${}之中)。

// 普通字符串
`In JavaScript '\n' is a line-feed.`

// 多行字符串
`In JavaScript this is
 not legal.`

console.log(`string text line 1
string text line 2`);

// 字符串中嵌入变量
let name = "Bob", time = "today";
`Hello ${name}, how are you ${time}?`

上面代码中的模板字符串,都是用反引号表示。如果在模板字符串中需要使用反引号,则前面要用反斜杠转义。

let greeting = `\`Yo\` World!`;

 大括号内部可以放入任意的 JavaScript 表达式,可以进行运算,以及引用对象属性,甚至能调用函数。

//运算
let x = 1;
let y = 2;

`${x} + ${y} = ${x + y}`
// "1 + 2 = 3"

`${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

由于模板字符串的大括号内部,就是执行 JavaScript 代码,因此如果大括号内部是一个字符串,将会原样输出。

`Hello ${'World'}`
// "Hello World"

 

5.标签模板 

标签模板其实不是模板,而是函数调用的一种特殊形式。“标签”指的就是函数,紧跟在后面的模板字符串就是它的参数。

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

//不带变量
alert`123`
// 等同于
alert(123)

//包含变量
let a = 5;
let b = 10;

tag`Hello ${ a + b } world ${ a * b }`;
// 等同于
tag(['Hello ', ' world ', ''], 15, 50);


//例子1
let a = 5;
let b = 10;

function tag(s, v1, v2) {
  console.log(s[0]);
  console.log(s[1]);
  console.log(s[2]);
  console.log(v1);
  console.log(v2);

  return "OK";
}

tag`Hello ${ a + b } world ${ a * b}`;
// "Hello "
// " world "
// ""
// 15
// 50
// "OK"


//例子2
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;
}

console.log(msg)

 “标签模板”的一个重要应用,就是过滤 HTML 字符串,防止用户输入恶意内容。

let sender = '<script>alert("abc")</script>';
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, "&amp;")
            .replace(/</g, "&lt;")
            .replace(/>/g, "&gt;");

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

 标签模板的另一个应用,就是多语言转换(国际化处理)

i18n`Welcome to ${siteName}, you are visitor number ${visitorNumber}!`
// "欢迎访问xxx,您是第xxxx位访问者!"

 模板处理函数的第一个参数(模板字符串数组),还有一个raw属性。

tag`First line\nSecond line`

function tag(strings) {
  console.log(strings.raw[0]);
  // strings.raw[0] 为 "First line\\nSecond line"
  // 打印输出 "First line\nSecond line"
}
console.log("First line\nSecond line")
//"First line
//Second line"

strings.raw数组就是["First line\\nSecond line"],strings.raw 数组会将\n视为\\和n两个字符,而不是换行符。这是为了方便取得转义之前的原始模板而设计的。

posted @ 2019-10-29 16:48  要变得更好呀!  阅读(185)  评论(0编辑  收藏  举报