ES6 字符串的扩展

本节我们来学习 ES6 中字符串类型的扩展,包括一些字符串对象的新增方法的使用等。

字符的 Unicode 表示法

ES6 加强了对 Unicode 的支持,JavaScript 中可以采用 \uxxx 形式表示一个字符,其中 xxxx 表示字符的码点。例如:

console.log("\u0075"); // u

但是这种表示法只限于码点在 \u0000~\uFFFF 之间的字符。超出这个范围的字符,必须用两个双字节的形式表示。

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

console.log("\u20BB8");  // 8

这表示,如果直接在 \u 后面跟上超过 0xFFFF 的数值,例如 \u20BB8,JavaScript 会理解成 \u20BB+8。由于 \u20BB 是一个不可打印字符,所以只会显示一个空格,后面跟着一个 8

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

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

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

let hello = 123;
console.log(hell\u{6F}); // 123

console.log('\u{1F680}' === '\uD83D\uDE80');  // true

上面代码中,最后一个例子表明,大括号表示法与四字节的 UTF-16 编码是等价的。

有了这种表示法之后,JavaScript共有6种方法可以表示一个字符。

'\z' === 'z'  // true
'\172' === 'z' // true
'\x7A' === 'z' // true
'\u007A' === 'z' // true
'\u{7A}' === 'z' // true

遍历器接口

ES6 为字符串添加了遍历器接口,使得字符串可以被 for...of 循环遍历。

示例:

例如我们遍历字符串 xkd

for (let i of 'xkd') {
    console.log(i)
}

输出:

x
k
d

除了遍历字符串,这个遍历器最大的优点是可以识别大于 0xFFFF 的码点,传统的 for 循环无法识别这样的码点。

示例:
let a = String.fromCodePoint(0x20BB7);

for (let i = 0; i < a.length; i++) {
  console.log(a[i]);
}


for (let i of a) {
  console.log(i);
}

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

模板字符串的使用

我们在 JavaScript 语言中,如果要输出内容,通常可以像下面这样写的:

var name = "侠课岛";
var age = 10;
console.log("我的名字是"+ name + ",我今年" + age + "岁了。" );

// 输出:我的名字是侠课岛,我今年10岁了。

这种写法需要使用大量的双引号和加号来拼接才能得到我们需要的模板,非常不方便。

而在 ES6 中提供了模板字符串,只需要将想要输出的内容用反引号标识,然后变量部分使用 ${} 括起来即可。

示例:

上面的例子可以用模板字符串写成下面这样:

var name = "侠课岛";
var age = 10;
console.log( `我的名字是${name} ,我今年${age}岁了。`);

// 输出:我的名字是侠课岛,我今年10岁了。

这样写很明显语法语法简洁了很多,不需要再使用大量的双引号和加号来拼接字符串和变量。

模板字符串都是使用反引号表示的,如果我们希望在模板字符串中使用反引号,则需要在前面使用反斜杠 \ 转义。

示例:
let content = `\`hello\` xkd!`;
console.log(content);  // 输出:`hello` xkd!

如果使用模板字符串表示多行字符串,所有的空格和缩进都会被保留在输出之中。

console.log( `你好\` 我叫做侠课岛,
 今年3岁啦!`);

执行代码后,会直接输出如下所示内容:

你好` 我叫做侠课岛,
 今年3岁啦!

在模板字符串中嵌入变量

如果我们想要在模板字符串中嵌入变量,那么变量需要写在 ${} 之中才能够正常使用,否则会当做普通字符串输出。

示例:
var name= "xkd";
console.log(`你好,${name}`);

// 输出:你好,xkd

但是如果模板字符串中的变量没有被声明,将导致报错哟。

let content = `Hello, ${name}`;
console.log(content);     // 输出:ReferenceError: name is not defined

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

let content = `Hello, ${"xkd"}`;
console.log(content);    // 输出:Hello, xkd

大括号 ${} 内部可以放入任意的 JavaScript 表达式,可以进行运算,以及引用对象属性。

var a = 10;
var b = 20;
console.log(`a=${++a}, b=${a+b}`);

// 输出:a=11, b=31

在模板字符串中调用函数

ES6 中模板字符串有一个更强大的功能,就是我们可以在模板字符串之中调用函数。

示例:
function show() {
  return "侠课岛";
}

console.log(`你好,你叫什么名字?
你好,我叫${show()}`);

执行代码后,输出内容如下所示:

你好,你叫什么名字?
你好,我叫侠课岛

如果大括号中的值不是字符串,将按照一般的规则转为字符串。比如,大括号中是一个对象,将默认调用对象的toString 方法。

判断是否包含子字符串

JavaScript 想要判断字符串是否包含子字符串,可以使用 indexOf() 方法。但是在 ES6 中又新增了三种方法可以用来判处案是否包含子字符串,如下所示:

  • includes():返回布尔值,表示是否找到了参数字符串。
  • startsWith():返回布尔值,表示参数字符串是否在原字符串的头部。
  • endsWith():返回布尔值,表示参数字符串是否在原字符串的尾部。
示例:

这三个方法都可以接受两个参数,第一个参数为需要搜索的字符串,第二个参数为可选的搜索起始位置索引:

let string = "hello, xkd";

console.log(string.includes("hello"));  // true
console.log(string.startsWith("x", 7)); // true
console.log(string.endsWith("abc"));    // false

注意上述方法的返回值都为布尔值,所以如果需要知道子字符串的位置,还是得用 indexOf()lastIndexOf() 方法。

字符串重复

ES6 中新增了一个 repeat() 方法,用于返回新的字符串,表示将字符串重复指定次数返回。

示例:
console.log("a".repeat(5));  // 输出:aaaaa

如果 repeat() 函数中的参数为小数,则会向下取整:

console.log("a".repeat(3.1));  // 输出:aaa
console.log("b".repeat(4.5));  // 输出:bbbb
console.log("c".repeat(5.9));  // 输出:ccccc

如果参数为 0-1 之间的小数,会进行取整运算,0-1 之间的小数取整得到 -0,等同于重复零次:

console.log("a".repeat(-0.1));  // 输出:""
console.log("b".repeat(-0.9));  // 输出:""

如果传入的参数是字符串,则会先将字符串转化为数字:

console.log("a".repeat("five")); // 输出: ""
console.log("b".repeat("3"));    // 输出: bbb

字符串补全

ES6 中为字符串补全提供了两个新的方法,如下所示:

  • padStart():返回新的字符串,表示用参数字符串从头部(左侧)补全原字符串。
  • padEnd():返回新的字符串,表示用参数字符串从尾部(右侧)补全原字符串。

这两个方法接受两个参数,第一个参数是指定生成的字符串的最小长度,第二个参数是用来补全的字符串。如果没有指定第二个参数,默认用空格填充。

示例:
console.log("xkd".padStart(5, "o")); // 输出:ooxkd 
console.log("a".padEnd(3, "xkd"));   // 输出:axk
console.log("b".padStart(3));        // 输出:  b

如果指定的长度小于或者等于原字符串的长度,则返回原字符串:

console.log("hello".padStart(3,"a"));  // hello
console.log("hello".padStart(7,"a"));  // aahello

如果原字符串加上补全字符串长度大于指定长度,则截去超出位数的补全字符串:

console.log("hello".padEnd(7,",xkd!"));    // hello,x
console.log("abcde".padEnd(10,"fghijk"));  // abcdefghij

还可以用于补全位数:

console.log("1".padStart(10, "0"));  // 0000000001
console.log("2".padEnd(10, "0"));    // 2000000000