ECMAScript 6之字符串的扩展
目录
- ECMAScript 6之字符串的扩展
- 1. 字符的 Unicode 表示法
- 2. 字符串遍历器接口
- 3. 行分隔符和段分隔符
- 4. 模板字符串
- 5. 标签模板
- 6. String.fromCodePoint()
- 7. String.prototype.codePointAt()
- 8. String.prototype.includes(),String.prototype.startsWith(),String.prototype.endsWith()
- 9. String.prototype.repeat()
- 10. String.prototype.padStart(),String.prototype.padEnd()
- 11. String.prototype.trimStart(),String.prototype.trimEnd()
- 11. 参考链接
1. 字符的 Unicode 表示法
ES6 加强了对 Unicode 的支持,允许采用\uxxxx
形式表示一个码点在\u0000~\uFFFF
之间的字符,其中xxxx
表示字符的 Unicode 码点。
'\u0061'; // 'a'
'\u0062'; // 'b'
对于Unicode码点超过0xFFFF
的数值,需要放入大括号中。
// 不放在{}中,会理解成\u20BB+8
"\u20BB8"; // "₻8"
// 放在{}中,正确解析
"\u{20BB8}"; // "𠮸"
2. 字符串遍历器接口
ES6 为字符串添加了遍历器接口,使得字符串可以被for...of
循环遍历。
for (let s of 'jidi') {
console.log(s)
}
// "j"
// "i"
// "d"
// "i"
字符串遍历器还可以识别大于0xFFFF
的码点。
const s = String.fromCodePoint(0x20BB8);
// 传统for循环不能识别大于0xFFFF的码点
for(let i = 0; i < s.length; i++) {
console.log(s[i]);
}
// " "
// " "
// for---of循环
for(let i of s) {
console.log(i)
}
// "𠮸"
3. 行分隔符和段分隔符
JavaScript 字符串允许直接输入字符,以及输入字符的转义形式。
// 两者等价
'中' === '\u4e2d' // true
JavaScript 中有5个字符,只能使用转义形式表示。
- U+005C:反斜杠。
- U+000D:回车。
- U+2028:行分隔符。
- U+2029:段分隔符。
- U+000A:换行符。
但是JSON格式中允许直接使用行分隔符和段分隔符,如果JSON中包含行分隔符或者段分隔符,用JSON.parse
解析,可能出现错误。为了解决这个问题,ES2019允许JavaScript 直接输入行分隔符和段分隔符。
// 允许直接使用行分隔符和段分隔符
let s1 = '\u2028';
let s2 = '\u2029'
4. 模板字符串
模板字符串是增强版的字符串,用反引号(`
)标识。它可以当作普通字符串使用,也可以用来定义多行字符串,或者在字符串中嵌入变量。
// 普通字符串
`模板字符串当做普通字符串使用`
// 多行字符串
`这是一个
多行模板字符串.`
console.log(`这也是一个
多行模板字符串`);
// 字符串中嵌入变量
let name = "jdii";
`你好,${name}, 吃早餐了吗?`
使用模板字符串表示多行字符串,所有的空格和缩进都会被保留在输出之中。
// 换行符和空格符都会保留
let s =
`<ul>
<li>first</li>
<li>second</li>
</ul>
`
模板字符串中嵌入变量,需要将变量名写在${}
之中。
function checkUser(user) {
if (user.name.length > 10) {
throw new Error(`您输入的用户名:${user.name}长度超过了10个字符!`)
}
}
大括号内部可以放入任意的 JavaScript 表达式,可以进行运算,引用对象属性和调用函数。
let x = 1;
let y = 2;
// 可以是表达式,可以参与运算
`${x} + ${y} = ${x + y}`; // "1 + 2 = 3"
// 可以调用对象属性
let person = {name: 'jidi', age: 22};
alert(`${person.name}`);
// 可以调用函数
function print() {
return "Hello World!";
}
`${print()} -----`; // Hello World!-----
如果大括号中的值不是字符串,将按照一般的规则转为字符串。
let person = {name: 'jidi', age: 22};
alert(`${person}`); // [object Object]
如果模板字符串中的变量没有声明,将报错。
let msg = `Hello, ${name}`; // Uncaught ReferenceError: place is not defined
5. 标签模板
模板字符串紧跟在一个函数名后面,该函数将被调用来处理这个模板字符串。这被称为“标签模板”功能。
alert`jidi`;
// 等价于
alert(['jidi'])
标签模板其实是函数调用的一种特殊形式。“标签”指的就是函数,紧跟在后面的模板字符串就是它的参数。
如果模板字符里面有变量,会将模板字符串先处理成多个参数,再调用函数。
let x = 'jidi';
let y = 'xuxiake';
function printStr(array, ...values){
let output = "";
let index;
for (index = 0; index < values.length; index++) {
output += array[index] + values[index];
}
output += array[index]
return output
}
printStr`${ x }对${ y }说:早上好!`; // "jidi对xuxiake说:早上好!"
上面代码中,函数printStr
第一个参数是一个数组,数组的成员是模板字符中没有被变量替换的部分,其它的参数都是模板字符串被变量替换后的值。
6. String.fromCodePoint()
ES5 提供的String.fromCharCode()
方法不能识别码点大于0xFFFF
的字符。为了识别大于0xFFFF
的字符ES6 提供了String.fromCodePoint()
方法。
// 不能识别大于0xFFFF的字符
String.fromCharCode(0x20BB8); // "ஸ"
// 可以识别大于0xFFFF的字符
String.fromCodePoint(0x20BB8); // "𠮸"
7. String.prototype.codePointAt()
JavaScript 内部,字符以 UTF-16 的格式储存,每个字符固定为2个字节。对于那些需要4个字节储存的字符(Unicode 码点大于0xFFFF
的字符),JavaScript 会认为它们是两个字符,字符串长度会误判为2,charCodeAt()
方法只能分别返回前两个字节和后两个字节的值。
ES6 提供了codePointAt()
方法,能够正确处理 4 个字节储存的字符,返回一个字符的码点。
let x = "𠮸";
// 长度会误判为2
x.length(); // 2
// charCodeAt方法会当做两个字符处理
x.charCodeAt(0).toString(16); // "d842"
x.charCodeAt(0).toString(16); // "dfb8"
// 正确识别四字节字符
x.codePointAt().toString(16); // "20bb8"
8. String.prototype.includes(),String.prototype.startsWith(),String.prototype.endsWith()
ES6 提供了三种新方法,判断一个字符串中是否包含子字符串。
- includes():返回布尔值,表示是否找到了参数字符串。
- startsWith():返回布尔值,表示参数字符串是否在原字符串的头部。
- endsWith():返回布尔值,表示参数字符串是否在原字符串的尾部。
let x = 'jidi';
x.startsWith('ji'); // true
x.endsWith('i'); // true
x.includes('d'); // true
上述三个方法都支持第二个参数index
,表示开始搜索的位置。但是endsWith
是针对前index
个字符,而includes
和startsWith
方法针对的是从第index
个位置开始到结束位置的字符。
let s = 'Hello world!';
// 针对的是第6个位置上的字符直到结束
s.startsWith('world', 6) // true
s.includes('Hello', 6) // false
// 针对的是前5个字符
s.endsWith('Hello', 5) // true
9. String.prototype.repeat()
repeat
方法返回一个新字符串,表示将原字符串重复n次。
'jidi'.repeat(2); // "jidijidi"
'jidi'.repeat(0); // ""
参数如果是小数,会被取整。
'jidi'.repeat(2.5); // "jidijidi"
参数是绝对值大于等于1
的负数或Infinity
,报错。
'jidi'.repeat(-1); // Uncaught RangeError: Invalid count value at String.repeat
'jidi'.repeat(Infinity); // Uncaught RangeError: Invalid count value at String.repeat
参数如果为绝对值小于1
的负数或者为NaN
,等同于参数为0
。
// 参数绝对值小于1的负数等同于0
'jidi'.repeat(-0.12); // ""
// NaN等同于0
'jidi'.repeat(NaN); // ""
参数是字符串,则会先转换成数字,然后参与运算。
'jidi'.repeat('jidi') // "jidi"转换为数字为NaN,结果为""
'jidi'.repeat('2') // "jidijidi"
10. String.prototype.padStart(),String.prototype.padEnd()
ES2017 引入了padStart()
和padEnd()
用于字符串补全长度。如果某个字符串不够指定长度,分别在头部或尾部补全字符串。
// 头部补充
'x'.padStart(5, 'jidi'); // "jidix"
'x'.padStart(4, 'jidi'); // "jidx"
// 尾部补充
'x'.padEnd(5, 'jidi'); // "xjidi"
'x'.padEnd(4, 'jidi'); // "xjid"
padStart()
和padEnd()
一共接受两个参数,第一个参数是字符串补全生效的最大长度n
,第二个参数是用来补全的字符串s
。
如果原来字符串的长度,已经等于或大于最大长度,则字符串补全不生效,返回原字符串。
// 原来字符串长度已经等于或大于最大长度,方法不生效,返回原字符串
'jidi'.padStart(2, 'ab'); // 'jidi'
'jidi'.padEnd(2, 'ab'); // 'jidi'
如果用来补全的字符串与原字符串,两者的长度之和超过了最大长度,则会截去超出位数的补全字符串。
'jidi'.padStart(10, 'this is a example'); // "this ijidi"
'jidi'.padEnd(10, 'this is a example'); // "jidithis i"
省略第二个参数,默认使用空格补全长度。
'jidi'.padStart(8); // " jidi"
'jidi'.padEnd(8); // "jidi "
11. String.prototype.trimStart(),String.prototype.trimEnd()
ES2019新增了trimStart()
和trimEnd()
这两个方法。分别用于消除首部和尾部的空格。它们返回的都是新字符串,不会修改原始字符串。
let s = " jidi ";
s.trim(); // "jidi"
s.trimStart(); // "jidi "
s.trimEnd(); // " jidi"
11. 参考链接
本篇博文是我自己学习笔记,原文请参考:ECMAScript 6 入门
如有问题,请及时指出!
欢迎沟通交流,邮箱:jidi_jidi@163.com。