ES6语法学习笔记
1 Let和const
- Let: 所声明的变量,只在let命令所在的代码块内有效。
const
声明一个只读的常量
。一旦声明,常量的值就不能改变。const一旦声明变量,就必须立即初始化
,不能留到以后赋值。类似final
2 解构赋值
- ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为
解构
(Destructuring)。 - 本质上,这种写法属于
“模式匹配”
,只要等号两边的模式相同,左边的变量就会被赋予对应的值
2.1 数组的解构赋值
可以从数组中提取值,按照对应位置,对变量赋值。
数组的元素是按次序排列的,变量的取值由它的位置决定
1
2
3
4
5
6
7
8
9
10
11
12
13
14let [a, b, c] = [1, 2, 3]
let [ , , third] = ["foo", "bar", "baz"];
let [head, ...tail] = [1, 2, 3, 4];
head // 1
tail // [2, 3, 4]
let [x, y, ...z] = ['a'];
x // "a"
y // undefined
z // []
let [x, y, z] = new Set(['a', 'b', 'c'])解构赋值
允许指定
默认值1
2
3
4
5
6
7
8
9let [foo = true] = [];
foo // true
let [x, y = 'b'] = ['a']; // x='a', y='b'
// 只有当一个数组成员严格等于undefined,默认值才会生效。
let [x, y = 'b'] = ['a', undefined]; // x='a', y='b'
let [x = 1] = [null];
x // null2.2 对象的解构赋值
- 对象的属性没有次序,
变量
必须与属性
同名,才能取到正确的值。
1
2
3
4
5
6
7
8
9let { foo, bar } = { foo: 'aaa', bar: 'bbb' };
foo // "aaa"
bar // "bbb"
let {foo} = {bar: 'baz'};
foo // undefined
const { log } = console;
log('hello') // hello如果变量名与属性名不一致,必须写成下面这样。
foo是匹配的模式,baz才是变量。真正被赋值的是变量baz,而不是模式foo。
1
2let { foo: baz } = { foo: 'aaa', bar: 'bbb' };
baz // "aaa"- 对象的属性没有次序,
解构也可以用于嵌套结构的对象
1
2
3
4
5
6
7
8
9let obj = {
p: [
'Hello',
{ y: 'World' }
]
};
let { p: [x, { y }] } = obj;
x // "Hello"
y // "World"对象
的
解构也可以指定
默认值- 默认值生效的条件是,对象的
属性值
严格等于undefined
。 - null与undefined不严格相等,所以是个有效的赋值,导致默认值不会生效。
1
2
3var {x, y = 5} = {x: 1};
x // 1
y // 5- 默认值生效的条件是,对象的
2.3 字符串的解构赋值
- 字符串被转换成了一个类似数组的对象
1 |
|
- 类似数组的对象都有一个
length
属性,因此还可以对这个属性解构赋值
1 |
|
2.4 用途
- 交换变量的值
交换变量x
和y
的值
1 |
|
从函数返回多个值
1
2
3
4
5
6
7
8
9
10
11
12
13
14// 返回一个数组
function example() {
return [1, 2, 3];
}
let [a, b, c] = example();
// 返回一个对象
function example() {
return {
foo: 1,
bar: 2
};
}
let { foo, bar } = example();提取 JSON 数据
1
2
3
4
5
6
7
8let jsonData = {
id: 42,
status: "OK",
data: [867, 5309]
};
let { id, status, data: number } = jsonData;
console.log(id, status, number);
// 42, "OK", [867, 5309]遍历 Map 结构
1
2
3for (let [key, value] of map) {
console.log(key + " is " + value);
}1
2
3
4
5
6
7
8// 获取键名
for (let [key] of map) {
// ...
}
// 获取键值
for (let [,value] of map) {
// ...
}输入模块的指定方法
1
const { SourceMapConsumer, SourceNode } = require("source-map");
3. 函数的扩展
3.1 参数设置默认值
ES6 允许为函数的参数设置默认值,即直接写在参数定义的后面。
1
2
3function log(x, y = 'World') {
console.log(x, y);
}1
2
3
4
5
6function foo({x, y = 5}) {
console.log(x, y);
}
foo({}) // undefined 5
foo({x: 1}) // 1 5
foo({x: 1, y: 2}) // 1 2由于大括号被解释为代码块,所以如果箭头函数直接返回一个对象,必须在对象外面加上括号,否则会报错。
1
let getTempItem = id => ({ id: id, name: "Temp" });
ES6 引入
rest 参数
(形式为 …变量名 ),用于获取函数的多余参数,这样就不需要使用 arguments 对象了。rest 参数搭配的变量是一个数组
,该变量将多余的参数放入数组中。⚠️: rest 参数之后不能再有其他参数(即只能是最后一个参数),否则会报错。
1
2
3
4
5
6
7
8
9
10function add(...values) {
let sum = 0;
for (var val of values) {
sum += val;
}
return sum;
}
// 利用 rest 参数,可以向该函数传入任意数目的参数。
add(2, 5, 3) // 10
4 数组的扩展
扩展运算符
(spread)是三个点( … )。它好比 rest 参数的逆运算,将一个数组转为用逗号分隔的参数序列。
任何定义了遍历器(Iterator)接口的对象(参阅 Iterator 一章),都可以用扩展运算符转为真正的数组。
1 |
|
用途:
该运算符主要用于
函数调用
。1
2
3
4
5
6function add(x, y) {
return x + y;
}
const numbers = [4, 38];
add(...numbers) // 42应用 Math.max 方法,简化求出一个数组最大元素的写法。
1
Math.max(...[14, 3, 77])
push 函数,将一个数组添加到另一个数组的尾部。
1
2
3let arr1 = [0, 1, 2];
let arr2 = [3, 4, 5];
arr1.push(...arr2);复制数组
1
2
3
4
5const a1 = [1, 2];
// 写法一
const a2 = [...a1];
// 写法二
const [...a2] = a1;合并数组
1
2
3
4
5const arr1 = ['a', 'b'];
const arr2 = ['c'];
const arr3 = ['d', 'e'];
[...arr1, ...arr2, ...arr3]
// [ 'a', 'b', 'c', 'd', 'e' ]与解构赋值结合,生成数组
如果将扩展运算符用于数组赋值,只能放在参数的最后一位,否则会报错。
1
2
3
4
5
6
7
8
9
10
11const [first, ...rest] = [1, 2, 3, 4, 5];
first // 1
rest // [2, 3, 4, 5]
const [first, ...rest] = [];
first // undefined
rest // []
const [first, ...rest] = ["foo"];
first // "foo"
rest // []将
字符串
转为真正的数组
1
2[...'hello']
// [ "h", "e", "l", "l", "o" ]map获取key
1
2
3
4
5
6let map = new Map([
[1, 'one'],
[2, 'two'],
[3, 'three'],
]);
let arr = [...map.keys()]; // [1, 2, 3]
5 对象的扩展
5.1 属性的简洁表示法
1 |
|
1 |
|
5.2 日志的打印
输出 user 和 foo 两个对象时,就是两组键值对,可能会混淆。把它们放在大括号里面输出,就变成了对象的简洁表示法,每组键值对前面会打印对象名,这样就比较清晰
1 |
|
5.3 解构赋值
对象的
解构赋值
用于从一个对象取值
,所有的键和它们的值,都会拷贝到新对象上面。解构赋值要求等号右边是一个对象,所以如果等号右边是 undefined 或 null ,就会报错,因为它们无法转为对象。
解构赋值必须是最后一个参数,否则会报错。
解构赋值
的拷贝是
浅拷贝
1 |
|
1 |
|
1 |
|
- 如果扩展运算符后面是字符串,它会自动转成一个类似数组的对象
1 |
|
5.4 链判断运算符
1 |
|
?. 运算符,直接在链式调用的时候判断,左侧的对象是否为 null 或 undefined 。如果是的,就不再往下运算,而是返回 undefined
1 |
|
5.5 ?? 判断运算符
||
: 左侧的值如果为 null,undefined,空字符串, false , 0 ,默认值会生效
??
: 左侧的值为 null 或 undefined 时,默认值会生效
1 |
|
6 对象的新增方法
6.1 Object.is()
严格相等运算符
( === )- 类型不同,直接返回false
- 两个复合类型(对象、数组、函数)的数据比较时,不是比较它们的值是否相等,而是比较它们是否指向同一个对象。
- 同一类型的原始类型的值(数值、字符串、布尔值)比较时,值相同就返回true,值不同就返回false
- undefined 和 null 与自身严格相等
相等运算符
( == )- 在比较不同类型的数据时,相等运算符会先将数据进行类型转换,然后再用严格相等运算符比较
Object.is()
它用来比较两个值是否严格相等,与严格比较运算符(===)的行为基本一致。
不同之处只有两个:一是 +0 不等于 -0 ,二是 NaN 等于自身。
1
2Object.is(+0, -0) // false
Object.is(NaN, NaN) // true
6.2 Object.assign()
Object.assign方法用于对象的合并,将源对象(source)的所有可枚举属性,复制到目标对象(target)
Object.assign
方法实行的是浅拷贝
,
1 |
|