在以往,我们都是通过单引号 '' 或 双引号"" 以及加号 + 这些连接符,来拼接字符串和变量 。比如,以下方式:

var num = 5,
price = 10;

console.log('There are have ' + num + ' orange, and total $' + price);
// 'There are have 5 orange, and total $10'

这种拼接方式其实很繁琐,特别是在变量和字符串都很多、或者字符串本身就有这些连接符的情况下。因为要反复写 +'' 等这些连接符,并且这种拼接方式也很容易出错。

针对以上ES5的问题,ES6 对字符串进行了一些方法和属性上的扩展。

一、模板字符串

为了更轻松的拼接字符串,ES6 引入了反引号 和美元符 $ 加花括号 {} 的形式,如下:

var num = 5,
price = 10;

console.log(`There are have ${num} orange, and total $${price}`);
// There are have 5 orange, and total $10

以上代码中,单引号被换成了反引号,变量则采用美元符加花括号的形式。这样一来,拼接字符串的工作就方便多了。

如果 ${} 里放置不是变量,而是字符串。则直接输入该字符串。

console.log(`Hello ${`world`}`); // 'Hello world'

如果 ${} 里放置不是变量,而是js代码。则直接运行该js代码,并且 ${} 中还可以再嵌套变量。

var number = 5;

function fn(num) {
return num*2;
}

console.log(`The number is ${fn(number)}`); // The number is 10

1.1 反引号转义

如果你要输入反引号本身,使用反斜杠转义下即可,用法和正则类似:

console.log(`o\`k`); // 'o`k'

1.2 多行字符串

使用单引号定义的变量,通常只能单行,如果强行多行的话,则会报错,如下:

var str1 = 'a
b
c';

console.log(str1);
// 报错:Invalid or unexpected token

但如果使用反引号定义变量,则可以输出包含多行字符串的变量,并且包括其中的空白符(换行符、缩进)都会被原原本本的输出来。

var str2 = `a
b
c`;

console.log(str2);
//'a
//b
//c'

二、标签模板

前面说到的 模板字符串 虽然很实用,但真正发挥威力的是 标签模板

所谓的 标签模板,就是在反引号 之前加入一个标识符,类似函数调用的效果,请看代码:

function fn(num) {
return num*2;
};

console.log(fn`10`); // 20

console.log(fn(10)); // 20

上面两种运行结果是等价的,其中第一种就是 标签模板。 其中这里的 fn 就是标签,我们可以自定义,而 10 就是标签(函数)的参数。

如果标签的参数里有变量,则情况就会变得复杂些,还是用一个例子来说明:

function tag(literals, ...substitutions) {

console.log(literals, literals.length);
// ["There are have ", " orange, and total $", "", raw: Array[3]] 3
console.log(substitutions, substitutions.length);
// [5, 10] 2
console.log(...substitutions);
// 5 10

var result = "";

for (var i = 0; i < substitutions.length; i++) {
result += literals[i];
result += substitutions[i];
}

result += literals[literals.length - 1];

return result;
}

var num = 5,
price = 10;

console.log(tag`There are have ${num} orange, and total $${price}`);
// There are have 5 orange, and total $10

由上面的代码可以知道,tag 函数的第一个形参为非变量的数组,这个数组是被变量拆分开来的。而第二个形参则是一组变量依次排列组成的数组。

虽然

tag`There are have ${num} orange, and total $${price}`

并没有按照 tag 函数所定义的形式传参,但是 tag 函数里的代码反应了如何将各个参数拼接起来,最终输出整个字符串。

如果你问我 标签模板 有什么用?我会告诉你,功夫都在 tag 函数里。因为 tag 函数中把参数分成了很多部分,因此你当然可以对每部分进行相应的处理,最终输出我们想要的字符串。

三、原始字符串 - String.raw()

在写代码时,我们都希望按照预期输出字符串,但有时候:

console.log(`a\nb`);
//'a
//b'

console.log(`\/`); // '/'

我们想要输出的是 a\nb\/,而并非js编译后的内容。 所以,ES6 提供了 String.raw 方法,用来返回原始的字符串。

console.log(String.raw`a\nb`);
// 'a\nb'

console.log(String.raw`\/`); // '\/'

除了上面反引号的用法,还有如下函数调用的形式:

String.raw({raw: str}, val1, val2, val3)

它的原生实现和使用大致如下:

String.raw = function (strings, ...values) {

console.log(strings); // {raw: "abc"}
console.log(values, values.length); // [0, 1] 2
console.log(...values); // 0 1

var output = '';
for (var index = 0; index < values.length; index++) {
output += strings.raw[index] + values[index];
}

output += strings.raw[index];
return output;
};

console.log(String.raw({ raw: 'abcd' }, 0, 1)); // 'a0b1c'

四、其他字符串方法

4.1 includes(), startsWith(), endsWith()

如果要检测字符串中是否存在某个字符串,我们通常会使用 indexOf 方法。而 ES6 又新增了三个方法,以方便我们更加精确的检测字符串:

  • includes() 返回布尔值,表示是否在字符串中找到某个字符,找到返回 true,反之则为 false 。
  • startsWith() 返回布尔值,表示字符串是否以某个字符开始,是返回 true,反之则为 false 。
  • endsWith() 返回布尔值,表示字符串是否以某个字符结尾,是返回 true,反之则为 false 。
var str = 'Hello world!';

console.log(str.includes('llo')); // true
console.log(str.startsWith('Hello')); // true
console.log(str.endsWith('!')); // true

console.log(str.includes('xlo')); // false
console.log(str.startsWith('ello')); // false
console.log(str.endsWith('!!')); // false

值得注意的是,这三个方法都能接受第二个参数,该参数为开始搜索字符串的位置索引。

不同的是,includes()startsWith() 方法是从第二个参数所在字符串的位置开始匹配。但 endsWith() 方法则是从字符串的第0位到第二个参数所在字符串的位置,这样一个范围进行匹配。

用一些代码来验证:

var str = 'Hello world!';

console.log(str.includes('llo', 2)); // true
console.log(str.includes('llo', 3)); // false

console.log(str.startsWith('o', 1)); // false
console.log(str.startsWith('o', 4)); // true

console.log(str.endsWith('wor', 3)); // false
console.log(str.endsWith('wor', 9)); // true

要包含 llo 字符,必须从字符串的第 2 位开始查找。

要以 o 字符开始,必须从字符串的第 4 位开始查找。

要以 wor 字符结束,必须是字符串的前 9 位。

另外,如果传入的第二个参数为数字字符串,比如 ‘9’ ,则函数会自动把它转换为数字 9。

4.2 repeat()

除了上面新增的那三个方法外,ES6 还增加了 repeat() 方法,用户可以给它传递一个数字作为参数,表示重复该字符串的次数,该方法返回一个包含原始字符串的新字符串。

来个例子:

console.log('hello'.repeat(2)); // 'hellohello'
console.log(' world'.repeat(3)); // ' world world world'

看,这对于循环输出一些文本特别有用。

注意,如果你传入的参数为一些特殊值,则该方法输出情况如下:

  • 0: 输出空字符串
  • 大于0小于1: 输出空字符串
  • 大于1的小数点:向下取整输出字符串的倍数
  • 小于0大于-1:输出空字符串
  • 小于-1:错误:Invalid count value
  • 数字字符串:向下取整输出字符串的倍数
  • 非数字:输出空字符串

用点代码来验证:

console.log('hello'.repeat(0)); // ''
console.log('hello'.repeat(0.6)); // ''
console.log('hello'.repeat(2.6)); // 'hellohello'
console.log('hello'.repeat(-0.6)); // ''
console.log('hello'.repeat(-1.1)); // 错误:Invalid count value

console.log('hello'.repeat('-3')); // 'hellohellohello'
console.log('hello'.repeat('abc')); // ''