ES6学习(8)-- 各数据类型扩展的汇总(1)

        ES6为JavaScript提供了新一代的标准,牵扯到各个方面,当然忘不了对原来数据类型的查缺补漏。相信看过阮一峰的ES6入门教程网站的人都知道,在ES6前几章节基本上都是各个数据类型的扩展。字符串扩展,数值扩展,正则扩展,函数扩展,数组扩展,对象扩展,运算符扩展。这简直就是把我们原来的数据类型扩展了个遍啊(幸亏null和underfined没得扩展)。

        本篇文章,我们不会逐条一个个的都学习一遍,我们要学习实际项目中经常用到的,剩下ES2021新添加的啊或者平时不常用的,大家就随便去瞅瞅就行了,知道出在哪里就好。哪怕到时候真的用到了,也可以知道去那里学习。随用随学吧。

1,字符串的扩展

模板字符串

        (详见请看我另一篇文章:ES6学习(5)-- 模板字符串

字符串的遍历器接口

        ES6 为字符串添加了遍历器接口,使得字符串可以被for...of循环遍历。除了遍历字符串,这个遍历器最大的优点是可以识别大于0xFFFF的码点,传统的for循环无法识别这样的码点。

let text = String.fromCodePoint(0x20BB7);

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

for (let i of text) {
  console.log(i);
}
// "𠮷"

String.fromCodePoint() 

         ES6提供了String.fromCodePoint()方法去识别大于0xFFFF的字符,弥补了ES5的String.fromCharCode()方法的不足。

String.fromCodePoint(0x20BB7)
// "𠮷"
String.fromCodePoint(0x78, 0x1f680, 0x79) === 'x\uD83D\uDE80y'
// true

String.row()

         ES6 还为原生的 String 对象,提供了一个raw()方法。该方法返回一个斜杠都被转义(即斜杠前面再加一个斜杠)的字符串,往往用于模板字符串的处理方法。

String.raw`Hi\n${2+3}!`
// 实际返回 "Hi\\n5!",显示的是转义后的结果 "Hi\n5!"

String.raw`Hi\\n`
// 返回 "Hi\\\\n"

String.raw`Hi\\n` === "Hi\\\\n" // true

codePointAt()

        ES6 提供了codePointAt()方法,能够正确处理 4 个字节储存的字符,返回一个字符的码点。

let s = '𠮷a';

s.codePointAt(0) // 134071
s.codePointAt(1) // 57271

s.codePointAt(2) // 97

includes() , startsWith() , endsWith()

         传统上,JavaScript 只有indexOf方法,可以用来确定一个字符串是否包含在另一个字符串中。ES6 又提供了三种新方法。

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

以上三种方法都支持有第二个参数,第二个参数为number,表示开始搜索的位置。但是要注意的是:使用第二个参数n时,endsWith的行为与其他两个方法有所不同。它针对前n个字符,而其他两个方法针对从第n个位置直到字符串结束。 

let s = 'Hello world!';

s.startsWith('world', 6) // true
s.endsWith('Hello', 5) // true
s.includes('Hello', 6) // false

repeat()

   repeat方法返回一个新字符串,表示将原字符串重复n次。

// n为正整数
'na'.repeat(3) // "nanana"

// n为小数会被取整,这里的取整就是单纯的取出来整数部分
'na'.repeat(2.9) // "nana"

// n为-1到0的小数,则判定为0
'na'.repeat(-0.9) // ""

// n为负数或者Infinity,会报错。
'na'.repeat(Infinity) // RangeError
'na'.repeat(-1)  // RangeError

//n是NaN等同于 0
'na'.repeat(NaN) // ""

// n是字符串,则会先转换成数字
'na'.repeat('na') // ""
'na'.repeat('3') // "nanana"

padStart() , padEnd()

        ES2017 引入了字符串补全长度的功能。如果某个字符串不够指定长度,会在头部或尾部补全。padStart()用于头部补全,padEnd()用于尾部补全。

规则:padStart()padEnd()一共接受两个参数,第一个参数是字符串补全生效的最大长度,第二个参数是用来补全的字符串。

// 如果原字符串的长度,等于或大于最大长度,则字符串补全不生效,返回原字符串。
'xxx'.padStart(2, 'ab') // 'xxx'
'xxx'.padEnd(2, 'ab') // 'xxx'

// 如果用来补全的字符串与原字符串,两者的长度之和超过了最大长度,则会截去超出位数的补全字符串
'abc'.padStart(10, '0123456789')  // '0123456abc'
'abc'.padEnd(10, '0123456789')    // "abc0123456"

// 如果省略第二个参数,默认使用空格补全长度
'x'.padStart(4)     // '   x'
'x'.padEnd(4)       // 'x   '

 replaceAll()

        原来的replace()方法只能替换第一个匹配到的子字符串,如果想要替换所有,就需要使用正则作为搜索对象并添加全局的 “ g ” 属性。为了简化此操作,ES2021 引入了replaceAll()方法,可以一次性替换所有匹配。

规则:它的用法与replace()相同,返回一个新字符串,不会改变原字符串。

'aabbcc'.replaceAll('b', '_')    // 'aa__cc'

// replaceAll()的第二个参数replacement是一个字符串,表示替换的文本,其中可以使用一些特殊字符串。
//  $&:匹配的字符串。
//  $` :匹配结果前面的文本。
//  $':匹配结果后面的文本。
//  $n:匹配成功的第n组内容,n是从1开始的自然数。这个参数生效的前提是,第一个参数必须是正则表达式。
//  $$:指代美元符号$。


// $& 表示匹配的字符串,即`b`本身
// 所以返回结果与原字符串一致
'abbc'.replaceAll('b', '$&')
// 'abbc'

// $` 表示匹配结果之前的字符串
// 对于第一个`b`,$` 指代`a`
// 对于第二个`b`,$` 指代`ab`
'abbc'.replaceAll('b', '$`')
// 'aaabc'

// $' 表示匹配结果之后的字符串
// 对于第一个`b`,$' 指代`bc`
// 对于第二个`b`,$' 指代`c`
'abbc'.replaceAll('b', `$'`)
// 'abccc'

// $1 表示正则表达式的第一个组匹配,指代`ab`
// $2 表示正则表达式的第二个组匹配,指代`bc`
'abbc'.replaceAll(/(ab)(bc)/g, '$2$1')
// 'bcab'

// $$ 指代 $
'abc'.replaceAll('b', '$$')
// 'a$c'


// replaceAll()的第二个参数replacement除了为字符串,也可以是一个函数,该函数的返回值将替换掉第一个参数searchValue匹配的文本。
'aabbcc'.replaceAll('b', () => '_')  // 'aa__cc'

2,正则的扩展

 RegExp 构造函数

        RegExp构造函数第一个参数是一个正则对象,那么可以使用第二个参数指定修饰符。而且,返回的正则表达式会忽略原有的正则表达式的修饰符,只使用新指定的修饰符。 

// ES5
var regex = new RegExp(/xyz/, 'i');  // Uncaught TypeError: Cannot supply flags when constructing one RegExp from another

//ES6
new RegExp(/abc/ig, 'i').flags   // "i"

RegExp.prototype.flags 属性  

        ES6 为正则表达式新增了flags属性,会返回正则表达式的修饰符。 

// ES5 的 source 属性
// 返回正则表达式的正文
/abc/ig.source
// "abc"

// ES6 的 flags 属性
// 返回正则表达式的修饰符
/abc/ig.flags
// 'gi'

 具名组匹配

         ES2018 引入了具名组匹配(Named Capture Groups),允许为每一个组匹配指定一个名字,既便于阅读代码,又便于引用。

规则:

“具名组匹配”在圆括号内部,模式的头部添加“问号 + 尖括号 + 组名”(?<year>),然后就可以在exec方法返回结果的groups属性上引用该组名。

具名组匹配等于为每一组匹配加上了 ID,便于描述匹配的目的。如果组的顺序变了,也不用改变匹配后的处理代码。

如果具名组没有匹配,那么对应的groups对象属性会是undefined

// 原来的正则组匹配的写法
// 想要获取到每个组的值,只能用数字序号(比如matchObj[1])引用,要是组的顺序变了,引用的时候就必须修改序号。
const RE_DATE = /(\d{4})-(\d{2})-(\d{2})/;
const matchObj = RE_DATE.exec('1999-12-31');
const year = matchObj[1]; // 1999
const month = matchObj[2]; // 12
const day = matchObj[3]; // 31

// ES2018引入具名组匹配的写法
// 想要获取到某个组的值,可以使用ID,在正则返回值的groups属性上直接读取。
const RE_DATE = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/;
const matchObj = RE_DATE.exec('1999-12-31');
const year = matchObj.groups.year; // "1999"
const month = matchObj.groups.month; // "12"
const day = matchObj.groups.day; // "31"

正则匹配索引 

        正则匹配结果的开始位置和结束位置,目前获取并不是很方便。原来正则实例的exec()方法,返回结果有一个index属性,可以获取整个匹配结果的开始位置,但是如果使用了组匹配,那么每个组的开始位置就无法得到了。

如何获取组匹配的组的开始和结束位置呢?ES6提供了一个新的方案:exec()方法的返回结果加上indices属性,在这个属性上面可以拿到匹配的开始位置和结束位置。

const text = 'zabbcdef';
const re = /ab+(cd(ef))/;
const result = re.exec(text);

result.indices // [ [1, 8], [4, 8], [6, 8] ]

// 说明:上面例子中,正则表达式中包含了两个组匹配,所以正则返回结果的indices属性就会返回三个元素的数组。其中,第一个元素是正则整体匹配结果('abbcdef')的开始位置和结束位置。第二个元素是第一个组匹配的结果('cdef')的开始位置和结束位置。第三个元素是第二个组匹配的结果('ef')的开始位置和结束位置。

 注意,

开始位置包含在匹配结果之中,但是结束位置不包含在匹配结果之中。比如,匹配结果为ab,分别是原始字符串的第1位和第2位,那么结束位置就是第3位。

如果获取组匹配不成功,indices属性数组的对应成员则为undefinedindices.groups属性对象的对应成员也是undefined

String.prototype.matchAll()  

        如果一个正则表达式在字符串里面有多个匹配,现在一般使用g修饰符或y修饰符,在循环里面逐一取出。ES2020增加了String.prototype.matchAll()方法,可以一次性取出所有匹配。不过,它返回的是一个遍历器(Iterator),而不是数组。 

const string = 'test1test2test3';
const regex = /t(e)(st(\d?))/g;

for (const match of string.matchAll(regex)) {
  console.log(match);
}
// ["test1", "e", "st1", "1", index: 0, input: "test1test2test3"]
// ["test2", "e", "st2", "2", index: 5, input: "test1test2test3"]
// ["test3", "e", "st3", "3", index: 10, input: "test1test2test3"]

3,数值的扩展 

 Number.isFinite()

        用来检查一个数值是否为有限的(finite),即不是Infinity。 Number.isFinite()方法只对数值有效,对于非数值一律返回false。

Number.isFinite(15); // true
Number.isFinite(0.8); // true
Number.isFinite(NaN); // false
Number.isFinite(Infinity); // false
Number.isFinite(-Infinity); // false
Number.isFinite('foo'); // false
Number.isFinite('15'); // false
Number.isFinite(true); // false

Number.isNaN()  

         用来检查一个值是否为NaN。Number.isNaN()只有对于NaN才返回true,非NaN一律返回false

Number.isNaN(NaN) // true
Number.isNaN(15) // false
Number.isNaN('15') // false
Number.isNaN(true) // false
Number.isNaN(9/NaN) // true
Number.isNaN('true' / 0) // true
Number.isNaN('true' / 'true') // true

 Number.parseInt(), Number.parseFloat() 

        ES6 将全局方法parseInt()parseFloat(),移植到Number对象上面,行为完全保持不变。 

Number.isInteger() 

        Number.isInteger()用来判断一个数值是否为整数。 

Number.isInteger(25) // true
Number.isInteger(25.1) // false
Number.isInteger() // false
Number.isInteger(null) // false
Number.isInteger('15') // false
Number.isInteger(true) // false

// 特殊情况1
Number.isInteger(25) // true
Number.isInteger(25.0) // true

// 特殊情况2: 数值的精度超过 53 个二进制位,第54位及后面的位就会被丢弃
Number.isInteger(3.0000000000000002) // true

 Math 对象的扩展

(1)、Math.trunc方法 :用于去除一个数的小数部分,返回整数部分。

Math.trunc(4.1) // 4
Math.trunc(-4.1) // -4

// 对于非数值,Math.trunc内部使用Number方法将其先转为数值。
Math.trunc('123.456') // 123
Math.trunc(true) //1
Math.trunc(false) // 0
Math.trunc(null) // 0

// 对于空值和无法截取整数的值,返回NaN
Math.trunc(NaN);      // NaN
Math.trunc('foo');    // NaN
Math.trunc();         // NaN
Math.trunc(undefined) // NaN

(2)、Math.sign方法:用来判断一个数到底是正数、负数、还是零。对于非数值,会先将其转换为数值。 

// 参数为负数,返回-1;
Math.sign(-5) // -1

// 参数为正数,返回+1;
Math.sign(5) // +1

// 参数为 0,返回0;
Math.sign(0) // +0

// 参数为-0,返回-0;
Math.sign(-0) // -0

// 其他值,返回NaN。
Math.sign(NaN) // NaN

//如果参数是非数值,会自动转为数值。对于那些无法转为数值的值,会返回NaN。
Math.sign('')  // 0
Math.sign(true)  // +1
Math.sign(false)  // 0
Math.sign(null)  // 0
Math.sign('9')  // +1
Math.sign('foo')  // NaN
Math.sign()  // NaN
Math.sign(undefined)  // NaN

到此为止!!!

各数据类型扩展的汇总(1)就结束了!!

东西很多,也比较杂乱,本篇文章中的都是我从原文中摘取出来的常见,常用,或者说有机会用到的 “ 芝士点 ”。大家可以浏览的看一遍,也不用死记硬背,知道在那里就好了,以后有用到了,再回来瞅瞅。

拜了个拜!迪迦。。。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值