头部背景图片
吉水于人的笔记 |
吉水于人的笔记 |

ES6常用总结

文章参考来源:[ECMAScript 6 入门]

阮一峰的文档讲的比较的详细,我当时在看的时候,也是没有太多的耐心,加上没有实战的话,忘的很快,所以决定根据每个章节,抽离出重要的知识点,将es6整个过一遍,文章中的示例均来源于文档。

一、let和const

  • let:申明一个变量,所申明的变量只在let命令所载代码块内有效。
    (1)循环中使用,循环体外引用报错
for (let i = 0; i < 10; i++) {

}
console.log(i);

// ReferenceError: i is not defined

(2)不存在变量提升,即必须声明后才可以使用

// var 的情况
console.log(foo); // 输出undefined
var foo = 2;

// let 的情况
console.log(bar); // 报错ReferenceError
let bar = 2;

(3)暂时性死区,作用域内存在let命令后,所声明的变量就绑定在该区域内,不再受外界的影响

var tmp = 123;

if (true) {
  tmp = 'abc'; // ReferenceError
  let tmp;
}

(4)不允许重复声明

// 报错
function func() {
  let a = 10;
  var a = 1;
}

// 报错
function func() {
  let a = 10;
  let a = 1;
}
  • const:声明一个只读常数,一旦声明,常量的值不可改变
    (1)只声明,不赋值,变量报错,与let一致,const只在声明所在的块级作用域内有效。
const foo;
// SyntaxError: Missing initializer in const declaration

if (true) {
  const MAX = 5;
}

MAX // Uncaught ReferenceError: MAX is not defined

(2)和let一致,也存在暂存性死区
(3)const保证变量指向的内存地址所保存的值不变,所以对于变量为数值、字符串、布尔值这样的简单数据类型,值直接保存在变量所指向的内存地址中,因此直接等于常量。但对于复合型数据,如对象和数组,变量指向但是内存地址,保存但是一个指向实际数据的指针,const只能保证这个指针是固定的,而它指向的数据结构是否可变是不可控制的。

const foo = {};

// 为 foo 添加一个属性,可以成功
foo.prop = 123;
foo.prop // 123
foo.prop = 235;
foo.prop // 235

// 将 foo 指向另一个对象,就会报错
foo = {}; // TypeError: "foo" is read-only

二、变量的解构赋值

  • 数组的解构赋值
    (1)解构不成功,变量的值变为undefined。不完全匹配的情况下,解构依然成功。
let [a, b, c] = [1, 2, 3];

let [foo, [[bar], baz]] = [1, [[2], 3]];  // foo:1,bar:2,baz:3

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] = [1, 2, 3];  // x:1,y:2

(2)等号右边为不可遍历的解构,解构报错

// 报错
let [foo] = 1;
let [foo] = false;
let [foo] = NaN;
let [foo] = undefined;
let [foo] = null;
let [foo] = {};

(3)对于 Set 结构,也可以使用数组的解构赋值

let [x, y, z] = new Set(['a', 'b', 'c']);
x // "a"

(4)指定默认值,指定默认值时,如果数组成员是null,默认值不会生效,因为null不严格等于undefined。如果默认值是一个表达式时,这个表达式是惰性的,即只有用到时,才会进行求值。

let [foo = true] = [];
foo // true

let [x, y = 'b'] = ['a']; // x='a', y='b'
let [x, y = 'b'] = ['a', undefined]; // x='a', y='b'

let [x = 1] = [undefined];
x // 1

let [x = 1] = [null];
x // null

function f() {
  console.log('aaa');
}

let [x = f()] = [1];
x // 1

(5)默认值可以引用解构赋值的其他变量,但是该变量必须已经声明

let [x = 1, y = x] = [];     // x=1; y=1
let [x = 1, y = x] = [2];    // x=2; y=2
let [x = 1, y = x] = [1, 2]; // x=1; y=2
let [x = y, y = 1] = [];     // ReferenceError: y is not defined
  • 对象的解构赋值
    (1)对象解构不需要按顺序来取值,变量与属性名相同,即可取到值,解构失败,变量的值等于undefined
let { bar, foo } = { foo: 'aaa', bar: 'bbb' };
foo // "aaa"
bar // "bbb"

let { baz } = { foo: 'aaa', bar: 'bbb' };
baz // undefined

(2)对象解构也可以用于嵌套结构的对象

let obj = {
  p: [
    'Hello',
    { y: 'World' }
  ]
};

let { p: [x, { y }] } = obj;
x // "Hello"
y // "World"

(3)如果解构模式是嵌套的对象,而子对象的父属性不存在,将会报错

// 报错
let {foo: {bar}} = {baz: 'baz'};

(4)对象的解构赋值可以取到继承的属性

const obj1 = {};
const obj2 = { foo: 'bar' };
Object.setPrototypeOf(obj1, obj2);

const { foo } = obj1;
foo // "bar"

(5)对象的解构也可以指定默认值,默认值生效的条件是,对象的属性严格等于undefined

var {x = 3} = {x: undefined};
x // 3

var {x = 3} = {x: null};
x // null

(6)对数组进行对象属性解构

let arr = [1, 2, 3];
let {0 : first, [arr.length - 1] : last} = arr;
first // 1
last // 3
  • 字符串解构赋值
const [a, b, c, d, e] = 'hello';
a // "h"
b // "e"
c // "l"
d // "l"
e // "o"

let {length : len} = 'hello';
len // 5
  • 数值和布尔值的解构赋值
    解构赋值时,如果等号右边是数值和布尔值,则会先转为对象,由于undefinednull无法转为对象,所以对它们进行解构赋值,都会报错。
let {toString: s} = 123;
s === Number.prototype.toString // true

let { prop: x } = undefined; // TypeError
let { prop: y } = null; // TypeError

*函数参数解构赋值

[[1, 2], [3, 4]].map(([a, b]) => a + b);  // [ 3, 7 ]

函数参数的解构也可以使用默认值,如果解构失败,参数值等于默认值,如果参数是一个对象,对这个对象进行解构,得到参数的值

function move({x, y} = { x: 0, y: 0 }) {
  return [x, y];
}

move({x: 3, y: 8}); // [3, 8]
move({x: 3}); // [3, undefined]
move({}); // [undefined, undefined]
move(); // [0, 0]

// undefined就会触发函数参数的默认值
[1, undefined, 3].map((x = 'yes') => x); // [ 1, 'yes', 3 ]

  • 不能使用圆括号
    (1)变量声明语句
// 全部报错
let [(a)] = [1];

let {x: (c)} = {};

let ({x: c}) = {};

let {(x: c)} = {};

let {(x): c} = {};

let { o: ({ p: p }) } = { o: { p: 2 } };

(2)函数参数声明

// 报错
function f([(z)]) { return z; }

// 报错
function f([z,(x)]) { return x; }

(3)赋值语句模式

// 全部报错
({ p: a }) = { p: 42 };

([a]) = [5];

[({ p: a }), { x: c }] = [{}, {}];
  • 可使用圆括号
    赋值语句非模式部分,可使用圆括号
[(b)] = [3]; // 正确
({ p: (d) } = {}); // 正确
[(parseInt.prop)] = [3]; // 正确

三、Set和Map数据结构

  • set:set数据结构类似于数组,但是成员的值是唯一的,没有重复值;set本身是一个构造函数,用来生成set数据结构

(1)去除数组重复成员

const set = new Set([1, 2, 3, 4, 4]);
[...set]  // [1, 2, 3, 4]

(2)set四个方法

  • add(value):添加某个值,返回 Set 结构本身。
  • delete(value):删除某个值,返回一个布尔值,表示删除是否成功。
  • has(value):返回一个布尔值,表示该值是否为Set的成员。
  • clear():清除所有成员,没有返回值。

(3)Array.from方法可以将 Set 结构转为数组

function dedupe(array) {
  return Array.from(new Set(array));
}

dedupe([1, 1, 2, 3]) // [1, 2, 3]

(4)遍历操作,set结构没有键名,只有键值,所以keysvalues方法得到的值是相同的

  • keys():返回键名的遍历器
  • values():返回键值的遍历器
  • entries():返回键值对的遍历器
  • forEach():使用回调函数遍历每个成员
let set = new Set(['red', 'green', 'blue']);

for (let item of set.keys()) {
  console.log(item);
}
// red
// green
// blue

for (let item of set.values()) {
  console.log(item);
}
// red
// green
// blue

for (let item of set.entries()) {
  console.log(item);
}
// ["red", "red"]
// ["green", "green"]
// ["blue", "blue"]

(5)数组的map和filter方法用于 Set

let a = new Set([1, 2, 3]);
let b = new Set([4, 3, 2]);

// 并集
let union = new Set([...a, ...b]);
// Set {1, 2, 3, 4}

// 交集
let intersect = new Set([...a].filter(x => b.has(x)));
// set {2, 3}

// 差集
let difference = new Set([...a].filter(x => !b.has(x)));
// Set {1}
  • WeakSet
    (1)WeakSet的成员只能是对象,不能是任何其他类型的值
    (2)WeakSet中的对象是弱引用,如果其他对象不再引用该对象,则垃圾回收机制会自动将该变量所占的内存进行回收,所以WeakSet只适合临时存储对象。WeakSet中对象拥有数量多少个,取决于垃圾回收机制什么时候运行,所以WeakSet的对象个数是不确定的,所以WeakSet不能进行遍历。
    (3)WeakSet是一个构造函数,可以使用new命令,创建WeakSet数据结构

  • Map
    (1)类似数组,键值对的集合,键的范围不局限于字符串,各种类型的值都可以做键。
    (2)Map如果对同一个键多次赋值,后面的值将覆盖前面的值

四、Promise 对象

Promise 是一种异步编程的解决方案。
(1)对象的状态不受外界影响。Promise对象代表一个异步操作,有三种状态:pending(进行中)、fullfilled(已成功)和rejected(已失败)
(2)一旦状态改变,就不会再变,任何时候都可以得到这个结果。对象状态的改变只能从pending到fullfilled或pending 到rejected。一旦情况发生了,其状态就已凝固,不会再发生改变。