ES6 | 小记
解构赋值
对es6解构赋值知识点的梳理。
数组的解构赋值
数组的解构赋值,元素是按次序排列,变量的取值是由它的位置决定;
// Before:
let a = 1,
let b = 2,
let c = 3
// Now:
let [a,b,c] = [1,2,3]
let [a,b] = [1]
a // > 1
b // > undefined
let [a,,c] = [1,2,3]
a // > 1
c // > 3
let [,,c] = [1,2,3]
c // > 3
// 用数组的解构赋值来交换两个变量的值
let a = 1;
let b = 2;
[a,b] = [b,a]
a // > 2
b // > 1
对于数组的解构,如果等号右边不是数组,那么进行解构将会报错;
let [a,b] = 1;
let [a] = true;
let [a] = NaN;
let [a,b] = {};
// > 以上都将报错
默认值
在解构的时候指定默认值,当解构的数组成员严格等于undefined,默认值才会生效;默认值也可以引用解构赋值的其它变量,前提是被引用的变量必须已经声明。
let [a,b = 2] = [1]
a // > 1
b // > 2
let [a,b = 2] = [1,null]
a // > 1
b // > null 这里的默认值不会生效,因为null不严格等于undefined
let [a = 1,b = a] = [] //引用变量a作为b的默认值
a // > 1
b // > 1
let [a = b, b = 1] = []
// > 报错 ReferenceError: b is not defined; 因为当a引用b作为默认值的时候,b还未被声明
对象的解构赋值
对象的解构与数组有一个重要的不同,对象的属性没有次序,变量必须与属性同名,才能取到正确的值。
let obj = {name: "jack",age: 22};
let {name, age} = obj;
name // > 'jack'
age // > 22
let {log} = console;
log('解构赋值') // > '解构赋值'
实际上,对象的解构赋值是下面形式的简写,被赋值的其实是后边的变量:
(对象的解构赋值的内部机制,是先找到同名属性,然后再赋给对应的变量。真正被赋值的是后者,而不是前者)
let {name: name,age: age} = {name: "jack",age: 22};
name // > 'jack'
let {name: who,age: howOld} = {name: "jack",age: 22}
who // > 'jack'
howOld // > 22
// 上述代码中,name是匹配的模式,who才是变量,真正被赋值的是变量who,而不是name
默认值
对象的解构赋值,只有当对象的属性值严格等于undifined的时候,默认值才会生效。
let {a = 3} = {}
a // > 3
let {a, b = 2} ={a: 1}
a // > 1
b // > 2
let {a: aaa = 222} = {}
aaa // > 222
let {a: aaa = 222} = {a: 111}
aaa // > 111
字符串的解构赋值
字符串也可以解构赋值。这是因为此时,字符串被转换成了一个类似数组的对象。
const [a,b,c,d,e] = 'hello';
a // > 'h'
b // > 'e'
c // > 'l'
d // > 'l'
e // > 'o'
类数组的对象都有一个length属性,我们可以对这个属性进行解构赋值
let {length} = 'hello'
length // > 5
函数参数的解构赋值
function fn([x,y]){
return x + y
}
fn([1,2]) // > 3
function fn([x = 1,y = 2]){
return x + y
}
fn([]) // > 3
[[1,2],[3,4]].map(([x,y])=>x + y) // >[3,7]
function fn({x = 1,y = 2}){
return x + y
}
fn({}) // > 3
function fn(){
return [1,2,3]
}
let [a,b,c] = fn()
a // > 1
b // > 2
c // > 3
function fn(){
return {a: 1,b: 2,c: 3}
}
let {a,b,c} = fn()
a // > 1
b // > 2
c // > 3
es6对几种数据类型的扩展
数值的扩展
- Number.isFinite()
用来检查一个数值是否为有限的,即不是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。如果参数类型不是NaN,Number.isNaN一律返回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.parseInt('12.34') // > 12
Number.parseFloat('123.45#') // > 123.45
- Number.isInteger()
用来判断一个数值是否为整数。如果参数不是数值,Number.isInteger返回false。
Number.isInteger(10) // > true
Number.isInteger(0) // > true
Number.isInteger(10.0) // > true
Number.isInteger(10.1) // > false
Number.isInteger() // > false
Number.isInteger(null) // > false
Number.isInteger('10') // > false
Number.isInteger(true) // > false
值得注意的是,由于js的精度问题,在下面这种情况下,Number.isInteger()可能会误判。
Number.isInteger(3.0000000000000002) // > true
类似情况还有,当一个数值的绝对值小于Number.MIN_VALUE(5E-324)[1],这时,Number.isInteger也会误判。
Number.isInteger(5E-324) // false
Number.isInteger(5E-325) // true
Math对象的扩展
- Math.trunc()
用于去除一个数的小数部分,返回整数部分。
Math.trunc(4.1) // 4
Math.trunc(4.9) // 4
Math.trunc(-4.1) // -4
Math.trunc(-4.9) // -4
Math.trunc(-0.1234) // -0
// 实现方式(对于没有部署这个方法的环境,可以模拟这个方法)
Math.trunc = Math.trunc || function (x){
return x < 0 ? Math.ceil(x) : Math.floor(x);
}
- Math.sign()
用来判断一个数到底是正数、负数、还是零。对于非数值,会先将其转换为数值。如果参数是非数值,会自动转为数值。对于那些无法转为数值的值,会返回NaN。
它的返回值:
参数为正数,返回+1;
参数为正数,返回+1;
参数为 0,返回0;
参数为-0,返回-0;
其他值,返回NaN。
Math.sign(-5) // -1
Math.sign(5) // +1
Math.sign(0) // +0
Math.sign(-0) // -0
Math.sign(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
字符串的新增方法
- includes(),startsWith(),endsWith()
includes():返回布尔值,表示是否找到了参数字符串。
startsWith():返回布尔值,表示参数字符串是否在原字符串的头部。
endsWith():返回布尔值,表示参数字符串是否在原字符串的尾部。
let s = 'Hello world!';
s.startsWith('Hello') // true
s.endsWith('!') // true
s.includes('o') // true
这三个方法都支持第二个参数,表示开始搜索的位置。
let s = 'Hello world!';
s.startsWith('world', 6) // true
s.endsWith('Hello', 5) // true
s.includes('Hello', 6) // false
- repeat()
返回一个新字符串,表示将原字符串重复n次。参数如果是小数,会被取整。
'x'.repeat(3) // "xxx"
'hello'.repeat(2) // "hellohello"
'na'.repeat(0) // ""
- padStart(),padEnd()
字符串补全长度的功能。如果某个字符串不够指定长度,会在头部或尾部补全。padStart()用于头部补全,padEnd()用于尾部补全。
padStart()和padEnd()一共接受两个参数,第一个参数是字符串补全生效的最大长度,第二个参数是用来补全的字符串。
'x'.padStart(5, 'ab') // 'ababx'
'x'.padStart(4, 'ab') // 'abax'
'x'.padEnd(5, 'ab') // 'xabab'
'x'.padEnd(4, 'ab') // 'xaba'
- trimStart(),trimEnd()
行为与trim()一致,trimStart()消除字符串头部的空格,trimEnd()消除尾部的空格。它们返回的都是新字符串,不会修改原始字符串。
let s = ' abc ';
s.trim() // "abc"
s.trimStart() // "abc "
s.trimEnd() // " abc"
浏览器还部署了额外的两个方法,trimLeft()是trimStart()的别名,trimRight()是trimEnd()的别名。
数组的扩展
- 扩展运算符
将一个数组转为用逗号分隔的参数序列。
let arr = [1,2,3,4]
console.log(...arr) // > 1,2,3,4
复制数组
// es5
const arr = [1,2,3]
const arr2 = arr.concant()
arr2 // > [1,2,3]
// es6扩展运算符
const arr = [1,2,3]
const arr2 = [...arr]
arr2 // > [1,2,3]
合并数组
const arr1 = ['a', 'b'];
const arr2 = ['c'];
const arr3 = ['d', 'e'];
// ES5 的合并数组
arr1.concat(arr2, arr3);
// [ 'a', 'b', 'c', 'd', 'e' ]
// ES6 的合并数组
[...arr1, ...arr2, ...arr3]
// [ 'a', 'b', 'c', 'd', 'e' ]
以上两种合并都是浅拷贝
其实字符串也可以使用扩展运算符转为数组
let arr = [...'我爱你中国']
arr // > ['我','爱','你','中','国']
Module语法
es6模块的设计思想是尽量的静态化,使得
编译时就能确定模块的依赖关系,以及输入和输出的变量。CommonJS 和 AMD 模块,都只能在运行时确定这些东西。
import和export的几种用法
以下几种写法,导出模块的文件统一命名成output.js;导入文件命名成entry.js。
写法1:
// output.js
export const name = 'clearLove';
// entry.js
import {name} from './output';
// 或者写成
import {name as newName} from './output'; //as关键字,将输入的变量重命名
写法2:
// output.js
const name = 'clearLove';
const fn = function(x,y){
return x + y
}
export {name,fn}
// entry.js
import {name,fn} from './output';
// 或者写成
import {name as newName,fn as newFn} from './output'; //as关键字,将输入的变量重命名
写法3:
// output.js
const name = 'clearLove';
export {
name as newName, //as关键字,将输出的变量重命名
}
// entry.js
import {newName} from './output';
写法4:
// output.js
export const name = 'clearLove';
export const fn = function(x,y){
return x + y ;
}
// entry.js
import * as output from './output';
console.log(output.name)
output.fn()
从以上几种方法可以看出,使用import命令的时候,用户需要知道所要加载的变量名或函数名,否则无法加载;为了给用户提供方便,让他们不用一一查看模块里的变量名或函数名就能加载模块,就要用到export default命令,为模块指定默认输出。以下方法为示例:
// output.js
export default function(x,y){
return x + y ;
}
// 或者写成
function fn(x,y){
return x + y ;
}
export default fn;
// entry.js
import fnfnfn from './output';
fnfnfn();
export与import 的复合写法
// entry.js
export { name, fn } from './output';
// 可以简单理解为
import { name, fn } from './output';
export { name, fn };
模块的接口改名和整体输出
// entry.js
// 接口改名
export { fn as fnfnfn } from './output';
// 整体输出
export * from './output';
具名接口改为默认接口
// entry.js
export { name as default } from './output';
// 等同于
import { name } from './output';
export default name;
还有一种写法:
// entry.js
export * as all from "./output";
// 等同于
import * as all from "./output";
export {all};
Number.MIN_VALUE(5E-324),即小于JavaScript能够分辨的最小值,会被自动转为0。 ↩︎

浙公网安备 33010602011771号