es6学习

es6第四章

1.字符的Unicode表示法

  • es6加强了对unicode的支持,允许采用\uxxxx形式表示一个字符,其中xxxx表示字符的Unicode码点
  • 例:
    \u0061 ==> "a"
  • 但是,这种表示法只限于码点在\u0000~\uFFFF之间的字符。超出这个范围的字符,必须用两个双字节的形式表示
  • ES6 对这一点做出了改进,只要将码点放入大括号,就能正确解读该字符

2.字符串的遍历器接口

  • ES6 为字符串添加了遍历器接口,使得字符串可以被for…of循环遍历
for (let codePoint of 'haha') {
  console.log(codePoint)
}
// "h"
// "a"
// "h"
// "a"
  • 除了遍历字符串,这个遍历器还可以识别大于0xFFF的码点

3.直接输入U+2028U+2029

  • JavaScript 字符串允许直接输入字符,以及输入字符的转义形式。举例来说,“中”的 Unicode 码点是 U+4e2d,你可以直接在字符串里面输入这个汉字,也可以输入它的转义形式\u4e2d,两者是等价的
    '中' === '\u4e2d' // true
  • 但是,JavaScript 规定有5个字符,不能在字符串里面直接使用,只能使用转义形式:

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

  • 举例来说,即字符串里面不能直接包含反斜杠
  • 这个规定本身没有问题,麻烦在于 JSON 格式允许字符串里面直接使用 U+2028(行分隔符)和 U+2029(段分隔符)。这样一来,服务器输出的 JSON 被JSON.parse解析,即有可能直接报错
  • 模板字符串现在就允许直接输入这两个字符。另外,正则表达式依然不允许直接输入这两个字符,这是没有问题的,因为 JSON 本来就不允许直接包含正则表达式

4.JSON.stringify()改造

  • 具体来说,UTF-8 标准规定,0xD800到0xDFFF之间的码点,不能单独使用,必须配对使用
  • \uD834\uDF06是两个码点,但是必须放在一起配对使用,代表字符?
  • JSON.stringify()的问题在于,它可能返回0xD800到0xDFFF之间的单个码点
    JSON.stringify('\u{D834}') // "\u{D834}"

5.模板字符串

  • 传统的 JavaScript 语言,输出模板通常是这样写的
$('#result').append(
  'There are <b>' + basket.count + '</b> ' +
  'items in your basket, ' +
  '<em>' + basket.onSale +
  '</em> are on sale!'
);
  • 而ES6引入了模板字符串
$('#result').append(`
  There are <b>${basket.count}</b> items
   in your basket, <em>${basket.onSale}</em>
  are on sale!
`);
  • 模板字符串是增强版的字符串,用反引号(`)标识,它可以当作普通字符串使用,也可以用来定义多行字符串,或者在字符串中嵌入变量
// 普通字符串
`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!`;
  • 如果使用模板字符串表示多行字符串,则空格和缩进都会被保留在输出之中
$('#list').html(`
<ul>
  <li>first</li>
  <li>second</li>
</ul>
`);
  • 上面代码中,所有模板字符串的空格和换行,都是被保留的,比如ul标签前面会有一个换行。如果你不想要这个换行,可以使用trim方法消除它,例:
$('#list').html(`
<ul>
  <li>first</li>
  <li>second</li>
</ul>
`.trim());
  • 模板字符串中嵌入变量,需要将变量名写在${}之中
  • 大括号内部可以放入任意的 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"
  • 模板字符串之中还能调用函数
  • 如果大括号中的值不是字符串,将按照一般的规则转为字符串。比如,大括号中是一个对象,将默认调用对象的toString方法
  • 由于模板字符串的大括号内部,就是执行 JavaScript 代码,因此如果大括号内部是一个字符串,将会原样输出
  • 模板字符串还能嵌套
const tmpl = addrs => `
  <table>
  ${addrs.map(addr => `
    <tr><td>${addr.first}</td></tr>
    <tr><td>${addr.last}</td></tr>
  `).join('')}
  </table>
`;

6.实例:模板编译

  • 通过模板字符串,生成正式模板的实例:
let template = `
<ul>
  <% for(let i=0; i < data.supplies.length; i++) { %>
    <li><%= data.supplies[i] %></li>
  <% } %>
</ul>
`;
  • 怎么编译这个模板字符串:将其转换为JavaScript表达式字符串
echo('<ul>');
for(let i=0; i < data.supplies.length; i++) {
  echo('<li>');
  echo(data.supplies[i]);
  echo('</li>');
};
echo('</ul>');
  • 这个转换使用正则表达式
let evalExpr = /<%=(.+?)%>/g;
let expr = /<%([\s\S]+?)%>/g;

template = template
  .replace(evalExpr, '`); \n  echo( $1 ); \n  echo(`')
  .replace(expr, '`); \n $1 \n  echo(`');

template = 'echo(`' + template + '`);';
  • 然后将template封装在一个函数里面返回
let script =
`(function parse(data){
  let output = "";

  function echo(html){
    output += html;
  }

  ${ template }

  return output;
})`;

return script;
  • 将上面的内容拼装成一个模板编译函数compile
  • compile的用法:
let parse = eval(compile(template));
div.innerHTML = parse({ supplies: [ "broom", "mop", "cleaner" ] });
//   <ul>
//     <li>broom</li>
//     <li>mop</li>
//     <li>cleaner</li>
//   </ul>

7.标签模板

  • 模板字符串还可以紧跟在一个函数名后面,该函数将被调用来处理这个模板字符串,这被称为标签模板功能
alert`123`
// 等同于
alert(123)
  • 标签模板其实不是模板,而是函数调用的一种特殊形式。“标签”指的就是函数,紧跟在后面的模板字符串就是它的参数
  • 但是在模板字符里面有变量,就不是简单的调用了,而是将模板字符串先处理成多个参数,再调用函数
let a = 5;
let b = 10;

tag`Hello ${ a + b } world ${ a * b }`;
// 等同于
tag(['Hello ', ' world ', ''], 15, 50);
  • 在代码中,模板字符串前面有一个标识名tag,是一个函数,表达式的返回值是tag函数处理模板字符串的返回值
  • tag函数的第一个参数是一个数组tag函数的其他参数,都是模板字符串各个变量被替换后的值。由于本例中,模板字符串含有两个变量,因此tag会接受到value1和value2两个参数
  • 即tag函数实际上以下面的形式调用:
    tag(['Hello ', ' world ', ''], 15, 50)
  • tag写法的例子:
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"
  • “标签模板”的一个重要应用,就是过滤 HTML 字符串,防止用户输入恶意内容
  • 另一个重要应用就是多语言管理
  • 模板处理函数的第一个参数(模板字符串数组),还有一个raw属性
console.log`123`
// ["123", raw: Array[1]]
  • console.log所接受的参数中的数组有一个raw属性,保存的是转义后的原字符串

8.模板字符串的限制

  • 前面的标签模板里面可以内嵌其他语言,但是模板字符串默认将字符串转义,最后导致无法潜入其他语言
  • 为了解决这个问题,ES2018 放松了对标签模板里面的字符串转义的限制。如果遇到不合法的字符串转义,就返回undefined,而不是报错,并且从raw属性上面可以得到原始字符串
function tag(strs) {
  strs[0] === undefined
  strs.raw[0] === "\\unicode and \\u{55}";
}
tag`\unicode and \u{55}`
  • 在代码中模板字符串原本是应该报错的,但是因为我们放松了对字符串转义的限制,所以不报错

注意,这种对字符串转义的放松,只在标签模板解析字符串时生效,不是标签模板的场合,依然会报错

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值