书到用时方恨少啊 于是2022年的规划又多了一项:多看书 不积跬步无以至千里 不积小流无以成江海
只记录对我来说比较陌生的知识点
文章内容来自: https://es6.ruanyifeng.com/
2022 / 1 / 7
变量的解构赋值
1:变量的解构赋值
ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring)。
解构赋值允许指定默认值。
代码语言:javascript复制let [foo = true] = [];
foo // true
let [x, y = 'b'] = ['a']; // x='a', y='b'
let [x, y = 'b'] = ['a', undefined]; // x='a', y='b
注意,ES6 内部使用严格相等运算符(===),判断一个位置是否有值。所以,只有当一个数组成员严格等于undefined,默认值才会生效。
如果一个数组成员是null,默认值就不会生效,因为null不严格等于undefined。
代码语言:javascript复制let [x = 1] = [undefined];
x // 1
let [x = 1] = [null];
x // null
如果默认值是一个表达式,那么这个表达式是惰性求值的,即只有在用到的时候,才会求值。
代码语言:javascript复制function f() {
console.log('aaa');
}
let [x = f()] = [1];
上面代码中,因为x能取到值,所以函数f根本不会执行。
2:对象的解构赋值
对象的属性没有次序,变量必须与属性同名,才能取到正确的值
如果变量名与属性名不一致,必须写成下面这样。
代码语言:javascript复制let { foo: foo, bar: bar } = { foo: 'aaa', bar: 'bbb' };
也就是说,对象的解构赋值的内部机制,是先找到同名属性,然后再赋给对应的变量。真正被赋值的是后者,而不是前者。
默认值
默认值生效的条件是,对象的属性值严格等于undefined。
代码语言:javascript复制var {x = 3} = {x: undefined};
x // 3
var {x = 3} = {x: null};
x // null
3:字符串的解构赋值
字符串也可以解构赋值。这是因为此时,字符串被转换成了一个类似数组的对象 类似数组的对象都有一个length属性,因此还可以对这个属性解构赋值
代码语言:javascript复制let {length : len} = 'hello';
len // 5
4: 数值和布尔值的解构赋值
解构赋值时,如果等号右边是数值和布尔值,则会先转为对象。
代码语言:javascript复制let {toString: s} = 123;
s === Number.prototype.toString // true
let {toString: s} = true;
s === Boolean.prototype.toString // true
上面代码中,数值和布尔值的包装对象都有toString属性,因此变量s都能取到值。
解构赋值的规则是,只要等号右边的值不是对象或数组,就先将其转为对象。由于undefined和null无法转为对象,所以对它们进行解构赋值,都会报错。
代码语言:javascript复制let { prop: x } = undefined; // TypeError
let { prop: y } = null; // TypeError
4:用途
从函数返回多个值
函数只能返回一个值,如果要返回多个值,只能将它们放在数组或对象里返回。有了解构赋值,取出这些值就非常方便。
代码语言:javascript复制// 返回一个数组
function example() {
return [1, 2, 3];
}
let [a, b, c] = example();
// 返回一个对象
function example() {
return {
foo: 1,
bar: 2
};
}
let { foo, bar } = example();
函数参数的定义
解构赋值可以方便地将一组参数与变量名对应起来。
代码语言:javascript复制// 参数是一组有次序的值
function f([x, y, z]) { ... }
f([1, 2, 3]);
// 参数是一组无次序的值
function f({x, y, z}) { ... }
f({z: 3, y: 2, x: 1});
提取 JSON 数据
解构赋值对提取 JSON 对象中的数据,尤其有用。
代码语言:javascript复制let jsonData = {
id: 42,
status: "OK",
data: [867, 5309]
};
let { id, status, data: number } = jsonData;
console.log(id, status, number);
// 42, "OK", [867, 5309]
上面代码可以快速提取 JSON 数据的值。
输入模块的指定方法
加载模块时,往往需要指定输入哪些方法。解构赋值使得输入语句非常清晰。
代码语言:javascript复制const { SourceMapConsumer, SourceNode } = require("source-map");
字符串的新增方法
实例方法: includes() startsWith() endsWith()
传统上,JavaScript 只有indexOf方法,可以用来确定一个字符串是否包含在另一个字符串中。ES6 又提供了三种新方法。
includes():返回布尔值,表示是否找到了参数字符串。 startsWith():返回布尔值,表示参数字符串是否在原字符串的头部。 endsWith():返回布尔值,表示参数字符串是否在原字符串的尾部。
代码语言:javascript复制let s = 'Hello world!';
s.startsWith('Hello') // true
s.endsWith('!') // true
s.includes('o') // true
这三个方法都支持第二个参数,表示开始搜索的位置。
代码语言:javascript复制let s = 'Hello world!';
s.startsWith('world', 6) // true
s.endsWith('Hello', 5) // true
s.includes('Hello', 6) // false
上面代码表示,使用第二个参数n时,endsWith的行为与其他两个方法有所不同。它针对前n个字符,而其他两个方法针对从第n个位置直到字符串结束。
实例方法:repeat()
repeat方法返回一个新字符串,表示将原字符串重复n次。
代码语言:javascript复制'x'.repeat(3) // "xxx"
'hello'.repeat(2) // "hellohello"
'na'.repeat(0) // ""
参数如果是小数,会被取整。 如果repeat的参数是负数或者Infinity,会报错。 但是,如果参数是 0 到-1 之间的小数,则等同于 0,这是因为会先进行取整运算。0 到-1 之间的小数,取整以后等于-0,repeat视同为 0。 如果repeat的参数是字符串,则会先转换成数字。 参数NaN等同于 0。
实例方法:padStart() padEnd()
ES2017 引入了字符串补全长度的功能。如果某个字符串不够指定长度,会在头部或尾部补全。padStart()用于头部补全,padEnd()用于尾部补全。
代码语言:javascript复制'x'.padStart(5, 'ab') // 'ababx'
'x'.padStart(4, 'ab') // 'abax'
'x'.padEnd(5, 'ab') // 'xabab'
'x'.padEnd(4, 'ab') // 'xaba'
上面代码中,padStart()和padEnd()一共接受两个参数,第一个参数是字符串补全生效的最大长度,第二个参数是用来补全的字符串。
如果原字符串的长度,等于或大于最大长度,则字符串补全不生效,返回原字符串。
代码语言:javascript复制'xxx'.padStart(2, 'ab') // 'xxx'
'xxx'.padEnd(2, 'ab') // 'xxx'
如果用来补全的字符串与原字符串,两者的长度之和超过了最大长度,则会截去超出位数的补全字符串。
代码语言:javascript复制'abc'.padStart(10, '0123456789')
// '0123456abc'
如果省略第二个参数,默认使用空格补全长度。
代码语言:javascript复制'x'.padStart(4) // ' x'
'x'.padEnd(4) // 'x '
padStart()的常见用途是为数值补全指定位数。下面代码生成 10 位的数值字符串。
代码语言:javascript复制'1'.padStart(10, '0') // "0000000001"
'12'.padStart(10, '0') // "0000000012"
'123456'.padStart(10, '0') // "0000123456"
另一个用途是提示字符串格式。
代码语言:javascript复制'12'.padStart(10, 'YYYY-MM-DD') // "YYYY-MM-12"
'09-12'.padStart(10, 'YYYY-MM-DD') // "YYYY-09-12"
实例方法: trimStart() trimEnd()
ES2019 对字符串实例新增了trimStart()和trimEnd()这两个方法。它们的行为与trim()一致,trimStart()消除字符串头部的空格,trimEnd()消除尾部的空格。它们返回的都是新字符串,不会修改原始字符串。
实例方法:replaceAll()
历史上,字符串的实例方法replace()只能替换第一个匹配。
代码语言:javascript复制'aabbcc'.replace('b', '_')
// 'aa_bcc'
上面例子中,replace()只将第一个b替换成了下划线。
如果要替换所有的匹配,不得不使用正则表达式的g修饰符。
代码语言:javascript复制'aabbcc'.replace(/b/g, '_')
// 'aa__cc'
正则表达式毕竟不是那么方便和直观,ES2021 引入了replaceAll()方法,可以一次性替换所有匹配。
代码语言:javascript复制'aabbcc'.replaceAll('b', '_')
// 'aa__cc'
它的用法与replace()相同,返回一个新字符串,不会改变原字符串。
实例方法 : at()
at()方法接受一个整数作为参数,返回参数指定位置的字符,支持负索引(即倒数的位置)。
代码语言:javascript复制const str = 'hello';
str.at(1) // "e"
str.at(-1) // "o"
如果参数位置超出了字符串范围,at()返回undefined。
数值的扩展
Number.isFinite(), Number.isNaN()
ES6 在Number对象上,新提供了Number.isFinite()和Number.isNaN()两个方法。
Number.isFinite()用来检查一个数值是否为有限的(finite),即不是Infinity。
注意,如果参数类型不是数值,Number.isFinite一律返回false。
Number.isNaN()用来检查一个值是否为NaN。
代码语言:javascript复制Number.isFinite('15'); // false
Number.isFinite(15); // true
Number.isNaN(NaN) // true
Number.isNaN("NaN") // false
Number.isInteger()
Number.isInteger()用来判断一个数值是否为整数。
代码语言:javascript复制Number.isInteger(25) // true
Number.isInteger(25.1) // false
JavaScript 内部,整数和浮点数采用的是同样的储存方法,所以 25 和 25.0 被视为同一个值。
代码语言:javascript复制Number.isInteger(25) // true
Number.isInteger(25.0) // true
如果参数不是数值,Number.isInteger返回false。
Number.EPSILON
ES6 在Number对象上面,新增一个极小的常量Number.EPSILON。根据规格,它表示 1 与大于 1 的最小浮点数之间的差。
对于 64 位浮点数来说,大于 1 的最小浮点数相当于二进制的1.00..001,小数点后面有连续 51 个零。这个值减去 1 之后,就等于 2 的 -52 次方。
Number.EPSILON实际上是 JavaScript 能够表示的最小精度。误差如果小于这个值,就可以认为已经没有意义了,即不存在误差了。
引入一个这么小的量的目的,在于为浮点数计算,设置一个误差范围。我们知道浮点数计算是不精确的。
安全整数和 Number.isSafeInteger()
JavaScript 能够准确表示的整数范围在-253到253之间(不含两个端点),超过这个范围,无法精确表示这个值。
代码语言:javascript复制Math.pow(2, 53) // 9007199254740992
9007199254740992 // 9007199254740992
9007199254740993 // 9007199254740992
Math.pow(2, 53) === Math.pow(2, 53) 1
// true
ES6 引入了Number.MAX_SAFE_INTEGER和Number.MIN_SAFE_INTEGER这两个常量,用来表示这个范围的上下限。 Number.isSafeInteger()则是用来判断一个整数是否落在这个范围之内
Math对象的扩展
Math.trunc
Math.trunc方法用于去除一个数的小数部分,返回整数部分。 对于非数值,Math.trunc内部使用Number方法将其先转为数值。
Math.sign()
Math.sign方法用来判断一个数到底是正数、负数、还是零。对于非数值,会先将其转换为数值。
它会返回五种值 参数为正数,返回 1; 参数为负数,返回-1; 参数为 0,返回0; 参数为-0,返回-0; 其他值,返回NaN。
粗体