ECMAScript 6之字符串的扩展

ECMAScript 6之字符串的扩展

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个字符,而includesstartsWith方法针对的是从第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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值