字符串扩展内容
一: 字符串扩展
1. 字符串中处理 Unicode 字符的方法
2. 字符串中遍历接口
3. 模板字符串
4. 常用 API
1. codePointAt
2. fromCodePoint
3. for...of...
4. includes
5. startsWith
6. endsWith
7. repeat
8. padStart
9. padEnd
10. raw
如图所示:
5-1-字符串扩展.png
补丁: 因为一些方法是 ES7 的提案, 如果我们不进行处理兼容性, 这些方法在 ES6 的编译中是无法通过的 。
安装补丁: cnpm i babel-polyfill --save-dev
同时我们需要将兼容库引入到入口文件 index.js (app/js/index.js) 中去 。
1. 字符串中处理 Unicode 字符的方法
{
console.log('Unicode 的表示方法(常规字符) -- a: ', '\u0061');
// 打印结果:
// Unicode 的表示方法(常规) -- a: a
}
{
// 当 Unicode 编码大于 0xFFFF, 即码值大于两个字节最大编码时, JS 会理解成 \u20BB+7; 由于 \u20BB 是一个不可打印字符, 所以会显示一个无法识别的内容, 后面跟一个 7 。
// console.log('当 Unicode 编码大于 0xFFFF 时, s: ', `\u20BB7`);
// 打印结果:(乱码 + 7)
// 当 Unicode 编码大于 0xFFFF 时, s: ₻7
}
{
// 正确处理大于 0xFFFF Unicode 编码: 使用大括号将内容包裹起来
console.log('使用大括号将 大于 0xFFFF Unicode 编码 内容包裹起来: ', `\u{20BB7}`);
// 打印结果: (注意: 这里不是 '吉莲' 的 '吉', 是一个字符)
// 使用大括号将内容包裹起来:
}
2. codePointAt() API
/**
2. codePointAt() API:
1. 与 Unicode 码点大于 0xFFFF 相关 。
2. codePointAt 方法会自动计算大于 4 个字节的码值 。
3. codePointAt 方法返回的是码点的十进制, 如果想要十六进制的值, 可以使用 toString(16) 方法转换 。
*/
// ES5 的处理方法:
{
let str1 = ''
// 打印长度:
// 因为当前字符的码节是大于 2 个字节的, 所以就将它当做 4 个字节; 而在计算长度时, 每两个字节就算是一个长度, 所以它的长度是 2 。
console.log('ES5 打印字符长度 - length: ', str1.length); // ES5 打印字符长度 - length: 2
/**
* 1. 对于这种四个字节的字符, JS 不能正常处理, 字符串长度会被误判为 2, charAt 无法读取整个字符;
* 2. charCodeAt 方法只能分别返回前两个字节与后两个字节 。
*/
// 获取编码: charAt()
console.log('ES5 获取编码 - 获取第一个位置的字符 - 0: ', str1.charAt(0)); // ES5 获取编码 - 获取第一个位置的字符 - 0: �
console.log('ES5 获取编码 - 获取第二个位置的字符 - 1: ', str1.charAt(1)); // ES5 获取编码 - 获取第二个位置的字符 - 1: �
// 获取码值: charCodeAt()
console.log('ES5 获取码值 - 获取第一个位置的字符的 Unicode 码值 - 0: ', str1.charCodeAt(0)); // ES5 获取码值 - 获取第一个位置的字符的 Unicode 码值 - 0: 55362
console.log('ES5 获取码值 - 获取第二个位置的字符的 Unicode 码值 - 1: ', str1.charCodeAt(1)); // ES5 获取码值 - 获取第二个位置的字符的 Unicode 码值 - 1: 57271
}
// ES6 的处理方法:
{
let str2 = 'a'
// 打印长度:
console.log('ES6 打印字符长度 - length: ', str2.length); // ES6 打印字符长度 - length: 3
/**
* 1. codePointAt 方法, 能够正确的处理 4 个字节存储的字符, 返回一个字符的码点 。
* 2. JS 将 'a' 处理为 3 个字符; codePointAt(0) 方法在第一个字符上正确的识别了 '', 返回它的十进制码点 134071, 十六进制为 20bb7 。
* 3. codePointAt(1) 第二个字符, 即 '' 的后两个字节, 码点为 57271 。
* 1. 问题: 为什么取 1 的时候, 它取了两个字节, 而不是在第四个字节后去取值 ?
* 1. 如果 codePointAt(1) 取得是第 5-6 个字节, 此时 codePointAt(1) 取得字符应该是 'a', 如果真的这样取值的它就会乱掉, 所以 codePointAt(1) 只取 '' 的后两个字节 。
* 4. codePointAt(2) 第三个字符 'a', 码点为 97 。
*/
// 获取码值: codePointAt()
console.log('ES6 获取码值 - 0 (默认 十进制): ', str2.codePointAt(0)); // ES6 获取码值 - 0 (默认 十进制): 134071
console.log('ES6 获取码值 - 0 (转化为 16进制: toString(16)): ', str2.codePointAt(0).toString(16)); // ES6 获取码值 - 0 (转化为 16进制: toString(16)): 20bb7
console.log('ES6 获取码值 - 1: ', str2.codePointAt(1)); // ES6 获取码值 - 1: 57271
console.log('ES6 获取码值 - 2: ', str2.codePointAt(2)); // ES6 获取码值 - 2: 97
}
3. fromCodePoint() 方法:
/**
3. fromCodePoint() 方法:
1. 用于从码点获取对应的字符 。
2. 与 codePointAt 获取码点, 是相反的功能 。
3. 能够处理 Unicode 编码大于 0xFFFF 的字符 。
4. 注意: fromCodePoint 方法定义在 String 对象上, 二 codePointAt 方法定义在字符串的实例对象上 。
*/
// ES5 处理方法:
{
let str1 = `0x20BB7`
// fromCharCode() 方法:
// fromCharCode 此方法不能识别 32 为的 UTF-16 字符, 即 Unicode 编码大于 0xFFFF 的字符 。
console.log('ES5 fromCharCode 用于从码点返回对应的字符:', String.fromCharCode(str1)); // ES5 fromCharCode 用于从码点返回对应的字符: ஷ
}
// ES6 处理方法:
{
let str2 = `0x20BB7`
// fromCharCode() 方法
console.log('ES6 fromCodePoint 用于从码点返回对应的字符:', String.fromCodePoint(str2)); // ES6 fromCodePoint 用于从码点返回对应的字符:
}
4. 字符串的遍历器接口: for...of...
/**
4. 字符串的遍历器接口: for...of...
1. 通过这个遍历器接口, 我们就可以正常处理字符串中包含 Unicode 编码大于 0xFFFF 的字符 。
*/
// ES5 方法: for 循环
{
let str = `\u{20BB7}abc`
for(let index = 0; index < str.length; index++) {
console.log('ES5: ', str[index]);
// 打印结果
// ES5: �
// ES5: �
// ES5: a
// ES5: b
// ES5: c
}
}
// ES6 方法: for...of... 循环
{
let str = `\u{20BB7}abc`
for (const val of str) {
console.log('ES6 :', val);
// 打印结果:
// ES6 :
// ES6 : a
// ES6 : b
// ES6 : c
}
}
5. includes() 方法:
/**
5. includes() 方法:
1. 判断字符串中是否包含某些字符 。
2. 返回布尔值: 包含返回 true; 不包含返回 false 。
3. indexOf() ES5 提供的方法, 返回某个指定的字符串值在字符串中首次出现的位置 。
1. 如果要检索的字符串值没有出现, 则该方法返回 -1。
*/
// ES5 方法
{
let strIndex = 'indexOfString'
let resTrue = strIndex.indexOf('dex')
let resFalse = strIndex.indexOf('bbb')
console.log('ES5 indexOf:', resTrue); // ES5 indexOf: 2
console.log('ES5 indexOf:', resFalse); // ES5 indexOf: -1
}
// ES6 方法
{
let strIn = 'includesStree'
let resTrue = strIn.includes('r')
let resFalse = strIn.includes('a')
console.log('includes - 判断字符串中是否包含某些字符 - resTrue: ', resTrue); // includes - 判断字符串中是否包含某些字符 - resTrue: true
console.log('includes - 判断字符串中是否包含某些字符 - resFalse: ', resFalse); // includes - 判断字符串中是否包含某些字符 - resFalse: false
}
6. startsWith() 方法
/**
6. startsWith() 方法
1. 判断字符串是否以某些字符为起始的 。
2. 返回布尔值: 参数字符串在源字符串换的头部 true; 参数没有在源字符串的头部 false 。
*/
{
let strStart = 'startString'
let resTrue = strStart.startsWith('star')
let resFalse = strStart.startsWith('aaa')
console.log('startsWith - 判断字符串是否以某些字符为起始的 - resTrue:', resTrue); // startsWith - 判断字符串是否以某些字符为起始的 - resTrue: true
console.log('startsWith - 判断字符串是否以某些字符为起始的 - resFalse:', resFalse); // startsWith - 判断字符串是否以某些字符为起始的 - resFalse: false
}
7. endsWith() 方法:
/**
7. endsWith() 方法:
1. 判断字符串是否以某些字符截止的 。
2. 返回布尔值: 参数字符串在源字符串换的尾部 true; 参数没有在源字符串的尾部 false 。
*/
{
let strEnd = 'endString'
let resTrue = strEnd.endsWith('ing')
let resFalse = strEnd.endsWith('bbb')
console.log('startsWith - 判断字符串是否以某些字符为截止的 - resTrue:', resTrue); // startsWith - 判断字符串是否以某些字符为截止的 - resTrue: true
console.log('startsWith - 判断字符串是否以某些字符为截止的 - resFalse:', resFalse); // startsWith - 判断字符串是否以某些字符为截止的 - resFalse: false
}
8. repeat() 方法:
/**
8. repeat() 方法:
1. 将源字符串重复
2. repeat 方法返回一个新的字符串 。
3. 注意一些细节:
1. 参数如果是小数, 会被取整
2. 如果 repeat 的参数是负数或者 Infinity, 会报错
3. 如果参数是 0 到 -1 之间, 则等同于 0; 因为会先进行取整运算; 0 到 -1 之间的小数取整之后等于 -0, repeat 视为 0 <参数为 NaN 等同于 0>。
4. 如果 repeat 的参数是字符串, 则先转换为数字 。
*/
{
let str = "repeat-"
let resRepeat = str.repeat(2);
console.log('repeat - 将源字符串重复:', resRepeat); // repeat - 将源字符串重复: repeat-repeat-
}
9. 模板字符串
/**
9. 模板字符串
1. 它是将数据和模板拼接成一个待结果的字符串 。
2. 小知识点:
1. 如果在模板字符串中需要使用反引号, 需要使用反斜杠转义: `\`You\` World` 。
2. 所有字符串模板中的 '空格' 和 '换行' 都是被保留的, 如果不想要这个换行, 可以使用 trim() 方法消除 。
3. 模板字符串中还可以调用函数 。
4. 如果大括号内部是一个字符串, 将会原样输出 。
*/
// ES5 方法
{
$('#id').append(
'this is ' + basket.count + '
' +
'items in your basket, ' +
'' + basket.price +
' are on sale'
)
}
// ES6 方法
{
let name = 'xiao hong'
let info = 'hello world'
// 拼接模板
/**
* 1. 必须使用 (`) 反引号包裹; 不是单引号, 也不是双引号 。
* 2. 其中的数据项必须通过 $美元符 + {}大括号 包裹起来 <变量必须声明, 否则会报错> 。
*/
let splitStr = `I am ${name}, ${info}`
console.log('ES6 - 模板字符串 - 拼接:', splitStr); // ES6 - 模板字符串 - 拼接: I am xiao hong, hello world
}
10. padStart() / padEnd() 方法
/**
10. padStart() / padEnd() 方法
1. 补白功能: padStart - 在前面补齐; padEnd - 在后面补齐 。
2. 第一个参数为: 长度 。
3. 第二个参数: 补白内容 (当设置的长度比实际长度大时, 空白使用第二个参数补齐) 。
4. 小知识点:
1. 如果省略第二个参数, 则会用 空格 补齐 。
2. 如果设置的第一个参数与源字符串的长度相等或小于源字符串的长度, 则返回源字符串 。
3. 如果用来补全的字符串与源字符串的长度之和超过了指定的最小长度, 则截去超出位数的补全字符串 。
5. 小功能:
1. 可以用来提示字符串格式 。
*/
{
console.log('padStart - 日期或号码: ', '1'.padStart(2, '0')); // 日期或号码: 01
console.log('padEnd - 日期或号码: ', '1'.padEnd(2, '0')); // 日期或号码: 10
}
11. 标签模板:
/**
11. 标签模板:
1. 标签模板其实不是模板, 而是函数调用的特殊形式 。
1. 标签指的就是函数, 紧跟在后面的模板字符串就是它的参数 。
*/
{
let obj = {
name: 'xiao lan',
info: '你好!'
}
fn`我是 ${obj.name}, ${obj.info}`
function fn(s, v1, v2) {
console.log('s: ', s, 'v1: ', v1, 'v2: ', v2);
// 打印结果:
// s: (3) ['我是 ', ', ', '', raw: Array(3)]
// v1: xiao lan
// v2: 你好!
}
}
// 防止 XSS 攻击特别好用 。
// 处理多语言转换也比较好用 。
{
let obj = {
name: 'xiao lan',
info: '你好!'
}
console.log('变换操作: ', fn`我是 ${obj.name}, ${obj.info}`);
// 打印结果:
// 变换操作: 我是 ,, ,xiao lan你好!
function fn(s, v1, v2) {
console.log('s: ', s, 'v1: ', v1, 'v2: ', v2);
// 打印结果:
// s: (3) ['我是 ', ', ', '', raw: Array(3)]
// v1: xiao lan
// v2: 你好!
return s+v1+v2
}
}
12. raw() 方法:
/**
12. raw() 方法:
1. 一般用来充当模板字符串的处理函数, 返回一个反斜线都被转义的字符串; 对应于替换变量后的模板字符串 。
*/
{
console.log('raw - use <换行符没有成效>: ', String.raw`Hi\n{1+2}`); // raw - use <换行符没有成效>: Hi\n{1+2}
console.log('raw - no <换行符生效>: ', `Hi\n{1+2}`);
// 打印结果:
// raw - no <换行符生效>: Hi
// {1+2}
}
函数执行结果, 如图所示:
之前有整理过部分知识点, 现在将整理的相关内容, 验证之后慢慢分享给大家; 这个专题是 "前端ES6基础" 的相关专栏; 不积跬步,无以至千里, 戒焦戒躁 。