让学习“上瘾”,成为更好的自己!!!
8 repeat()
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>repeat()</title>
</head>
<body>
<script>
// repeat()方法返回一个新字符串,表示将原字符串重复n次
console.log('hhee'.repeat(3));
// 参数是小数,会被取整
console.log('hhee'.repeat(2.6));
// 参数是负数或者Infinity,会报错
// console.log('hhee'.repeat(-2));
// console.log('hhee'.repeat(Infinity));
// 参数是0~1之间的小数,则等于0
console.log('hhee'.repeat(0.2));
// 参数NaN等于0
console.log('hhee'.repeat(NaN));
// 参数是字符串,则会先被转换成数字
console.log('hhee'.repeat('2.3'));
</script>
</body>
</html>
9 padStart() padEnd()
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>padStart() padEnd()</title>
</head>
<body>
<script>
// ES6引入“字符串补全长度”功能 --> 如果某个字符串不够指定长度,会在头部或者尾部补全
// padStart() --> 头部补全
// padEnd() --> 尾部补全
console.log('x'.padStart(5, 'ab')); // ababx
console.log('x'.padStart(4, 'ab')); // abax
console.log('x'.padEnd(5, 'ab')); // xabab
console.log('x'.padEnd(4, 'ab')); // xaba
// 接收2个参数:1, 指定字符串的最小长度;
// 2, 用来补全的字符串
// 如果原字符串的长度等于或大于指定的最小长度,则返回原字符
console.log('xxx'.padEnd(2, 'ab')); // xxx
console.log('xxx'.padEnd(2, 'ab')); // xxx
// 如果用来补全的字符串与原字符串的长度之和超过了指定的最小长度,则会截去超出位数的补全字符串
console.log('abc'.padEnd(10, '0123456789')); // abc0123456
// 如果省去第二个参数,则会用空格来补全
console.log('xxx'.padEnd(6)); // 'xxx '
console.log('xxx'.padStart(6));
// --------------padStart()方法的用途-----------------
// padStart的常见用途是:为数值补全指定位数【重要!!】
console.log('1'.padStart(10, '0'));
console.log('123'.padStart(10, '0'));
console.log('1234'.padStart(10, '0'));
// 另一个用途是:提示字符串的格式
console.log('12'.padStart(10, 'YYYY-MM-DD'));
console.log('09-12'.padStart(10, 'YYYY-MM-DD'));
</script>
</body>
</html>
10 模板字符串
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>模板字符串</title>
</head>
<body>
<script>
// 模板字符串:增强版的字符串,用反引号(`)标识。可以当普通字符串使用,也可以用来定义多行字符串,或者在字符串中嵌入变量
// 普通字符串
var a = `In JavaScript '\n' is a line-feed.`;
console.log(a);
// 多行字符串
var b = `In JavaScript this is
not legal`;
console.log(b);
// 字符串嵌入变量 --> ${变量}
var name = 'kai',
time = 'today';
console.log(`hello ${name}, how are you ${time}?`);
// (2) 如果在模板字符串中需要使用反引号,则在其前面用反斜线转义
var greeting = `\`Yo\`world!`;
console.log(greeting);
// (3) 使用模板字符串表示多行字符串,所有的空格和缩进都会被保留在输出中
var b = `In JavaScript this is
not legal`;
console.log(b);
// 不要换行可以使用trim()方法消除 --> 只限开头或结尾处
var b1 = `
In JavaScript this is
not legal
`.trim();
console.log(b1);
// (4) 在模板字符串中嵌入变量,需要将变量名写在${}中
var name = 'kai',
time = 'today';
console.log(`hello ${name}, how are you ${time}?`);
// 大括号可以放在任意的JavaScript表达式,可以进行运算,以及引用对象的属性
var x = 1,
y = 2;
var result1 = `${x} + ${y} = ${x + y}`;
console.log(result1);
var result2 = `${x} + ${y *2} = ${x + y * 2}`;
console.log(result2);
var obj = {x:1, y: 3};
console.log(`${obj.x + obj.y}`);
// (5) 模板字符串中还能调出函数
function fn(){
return 'hello world';
}
console.log(`foo ${fn()} bar`);
// (6) 如果大括号中的值不是字符串,将按照一般的规则转换成字符串
// 比如,大括号中是一个对象,将默认调用对象的toString()方法
// 如果模板字符串中的变量没有声明,将报错
var obj1 = {x: 're12'};
console.log(`this is a ${obj1}`);
// var message = `Hello ${place}`; // 报错
// (7) 由于模板字符串的大括号内部是要执行的JavaScript代码,因此如果大括号内部是一个字符串,将会原样输出
console.log(`hello ${'world'}!`);
// (8) 模板字符串可以嵌套
const tmpl = addrs => `
<table>
${addrs.map(addr => `
<tr><td>${addr.first}<td><tr>
<tr><td>${addr.last}<td><tr>
`).join('')}
</table>
`;
const data = [
{first: '<Jame>', last: 'Bond'},
{first: 'Lars', last: '<Croft>'}
];
console.log(tmpl(data));
data.map(d => {
console.log(`${d.first} and ${d.last}`);
})
// (9) 如果需要引用模板字符串本身,可以如下书写:
// way 1
let str = 'return' + '`Hello ${name}!`';
let func = new Function('name', str);
console.log(func('Jack')); // ” Hello Jack !”
// way 2
// let str = '(name) => `Hello ${name}!`';
// let func = eval.call(null, str);
// console.log(func('Kai'));
var sum = new Function('num1','num2','return num1 + num2');
console.log(sum(12, 3));
console.log(eval('sum(12, 1)'));
</script>
</body>
</html>
11 实例:模板编译
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>实例:模板编译</title>
</head>
<body>
<script>
// 下面的代码在模板字符串中放置了一个常规模板
// 该模板使用<%...%>放置JavaScript代码
// 使用<%=...%>输出JavaScript表达式
var template = `
<ul>
<% for(var i=0; i < data.supplies.length; i ++){ %>
<li><%= data.supplies[i] %></li>
<% } %>
</ul>
`;
// 如何编译这个模板字符串呢?
// way 1: 将其转换为JavaScript表达式字符串
// echo('<ul>');
// for (var i = 0; i < data.supplies.length; i++) {
// echo('<li>');
// echo(data.supplies[i]);
// echo('</li>');
// };
// echo('</ul>');
// 【注意】涉及该部分知识在来看!!!
</script>
</body>
</html>
12 标签模板
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>标签模板</title>
</head>
<body>
<script>
// alert`123`; // 模板字符串可以直接跟在一个函数名后边,该函数将被调用来处理这个模板字符串 --> “标签模板”功能
// 等价于alert(123)
// (1) 标签模板不是模板,而是函数调用的一种特殊的形式!
// “标签”指的是函数,紧跟在其后面的模板字符串就是他的参数
// (2) 如果模板字符串中有变量,则不再是简单的调用,而是要将模板字符串先处理成多个参数,在调用函数
// var a = 5,
// b = 10;
// tag`Hello ${a + b} world ${a * b}`;
// 等价于tag(['Hello ', ' world ', ''], 15, 50);
// 【解释】tag是一个函数,整个表达式的返回值就是tag函数处理模板字符串后的返回值
// tag函数会一次接收多个参数
// tag函数的第一个参数就是一个数组,该数组的成员是模板字符串中那些“没有变量替换”的部分
// 变量替换只发生在数组的第一个成员和第二个成员之间、第二个成员和第三个成员之间,以此类推
// tag函数的其他参数都是模板字符串各个变量“被替换”后的值
// 模板字符串中有两个变量,因此tag会接收到value1 and value2两个参数
// 该题中,tag函数的所有参数为:
// 第一个参数:['Hello ', ' world ', '']
// 第二个参数;15
// 第三个参数:50
function tag(stringArr, value1, value2){
// ........
}
// 等价于
function tag(stringArr, ...values){
// .......
}
// example 1
var a = 5,
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);
}
// tag`Hello ${a + b} world ${a * b}`;
// example 2
var total = 30;
var msg = passthru`The total is ${total} (${total * 1.05} with tax)`;
// 写法一
function passthru(literals){
var result = '';
var i = 0;
console.dir(literals); // ["The total is ", " (", " with tax)"]
console.dir(arguments); // ["The total is ", " (", " with tax)", raw: Array(3)], 30, 31.5
while (i < literals.length){
result += literals[i ++];
if (i < arguments.length){
result += arguments[i];
}
}
return result;
}
console.log(msg);
// 写法二
// function passthru(literals, ...values){
// var output = '';
// for (var index = 0; index < values.length; index ++){
// output += literals[index] + values[index];
// }
// output += literals[index];
// return output;
// }
// (3) 应用!!
// 【应用1】“标签模板”的一个重要应用是过滤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, '>');
// Dont escape special characters in the template
s += templateData[i];
}
return s;
}
// console.log(SaferHTML`<p>${sender} has sent you a message.</p>`);
// 涉及了再来看!!!
// 【应用2】多语言转换(国际化处理)
// 【应用3】使用标签模板在JavaScript语言中嵌入其他语言
// (4) 模板处理函数的第一个参数(模板字符串数组)还有一个raw属性
console.log`123`; // ["123", raw: Array(1)]
// --> console.log接收的是一个数组,该数组有一个raw属性,保存的是转义后的原字符串
tag`First line\nSecond line`;
function tag(strings){
console.log(strings);
console.log(strings.raw[0]); // First line\nSecond line
}
// tag函数的第一个参数strings有一个raw属性,指向一个数组,该数组成员与strings数组完全一致
// 唯一区别:strings.raw属性中的字符串中的斜杠都被转义了,即raw数组会将\n看成\\ and n 两个字符
</script>
</body>
</html>
13 String.raw()
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>String.raw()</title>
</head>
<body>
<script>
// ES6为原生的String对象添加添加了raw()方法
// String.raw: 用来充当模板字符串的处理函数,返回一个反斜线都被转义(即反斜线前面再加一个反斜线)的字符串,对应于替换变量后的模板字符串
console.log(String.raw`Hi\n${2+3}!`); // 'Hi\n5!'
console.log(String.raw`Hi\u000A!`); // 'Hi\u000A!'
// 如果原字符串中的反斜线已经转义,那么String.raw不会做任何处理
console.log(String.raw`Hi\\n`); // 'Hi\\n'
// String.raw方法也可以作为正常的函数使用。
// 第一个参数是一个具有raw属性的对象,且raw属性的值应该是一个数组
console.log(String.raw({raw: 'test'}, 0, 1, 2)); // t0e1s2t
console.log(String.raw({raw: ['t', 'e', 's', 't']}, 0, 1, 2)); // t0e1s2t
</script>
</body>
</html>
14 模板字符串的限制
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>模板字符串的限制</title>
</head>
<body>
<script>
// 标签模板中可以内嵌其他语言,但是模板字符串默认会将字符串转义,导致无法嵌入其他语言
// 例如标签模板中可以嵌入LaTeX语言,但在JavaScript中会报错,原因在于字符串转义
// 【提案】
// 放松对标签模板里边字符串转义的限制,如果遇到不合法的字符串转义,就返回undefined,而不是报错,并且从raw属性上可以得到原始字符串
// function tag(strs) {
// strs[0] === undefined
// strs.raw[0] === '\\unicode and \\u{55}';
// }
// tag`\unicode and \u{55}`
// 【注意】这种对字符串转义的放松只在标签模板解析字符串时生效,非标签模板的场合依然会报错
// let bad = `bad escape sequence: \unicode`; // 报错
</script>
</body>
</html>