公司中老项目是运用ES5写成了,现在全面升级ES6,固将以前学习过ES6的知识在重温一遍。

数组扩展

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
{
// 转化一组数据变为数组
let arr = Array.of(3,4,5,6);
console.log(arr) // [3,4,5,6]
// 将类数组转化为标准数组
let p = document.querySelectorAll('p'); // DOM节点组是类数组,可以for循环,但是不具备数组的方法比如forEach
let pArr = Array.from(p); // 转化为了标准数组
// 第二种用法,可以在转换时进行遍历
Array.from([1, 3, 5], function(item){ return item * 2}) // [2, 6, 10]
// 填充
[1, 'a', undefined].fill(7) // [7, 7, 7]
['a', 'b', 'c'].fill(7, 1, 3) // ['a', 7, 7] 后面两个参数是起始index和结束index
}
{
// .keys() 返回数组的index
for (let index of ['1', 'c', 'ks'].keys()){
console.log('keys', index) // 0 1 2
}
// .values() 返回数组的值
// .entries()
for (let [index, value] of ['1', 'c', 'ks'].entries()){
console.log('values', index, value)
}
}
{
let arr = [1,2,3,4,5];
arr.find(function(item){
return item > 3;
}) // 4 只找第一个,返回值
arr.findIndex(function(item){
return item > 3;
}) // 3 只找第一个,返回序号
arr.findIndex(function(item){
return item > 3;
}) // 3 只找第一个,返回序号
arr.includes(1) // true
}

函数扩展

  • 参数默认值
  • rest参数
  • 扩展运算符
  • 箭头函数 (this绑定)
  • 尾调用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// 默认参数(带有默认值的参数必须写在最后一个)
function test(x, y = 'world'){
console.log(x,y);
}
test('hello') // hello world
let x = 'test';
function test2(x, y=x){
console.log('作用域', x, y)
}
test2('kill') // kill kill 赋值是在函数里进行的 (如果把函数的第一个参数改成z,y就取外层的x)
{
// 在不确定参数数量时
function test3(...arg){
for (let v of arg){
console.log('rest', v)
}
}
}
// 箭头函数,this在箭头函数中指向调用函数的对象
{
let arrow = v => v * 2;
let arrow1 = () => 5;
console.log(arrow(2)) // 4
}
// 尾调用
{
function f(x){
return g(x);
}
// 尾调用由于是函数的最后一步操作,所以不需要保留外层函数的调用帧,因为调用位置、内部变量等信息都不会再用到了,只要直接用内层函数的调用帧,取代外层函数的调用帧就可以了。
}

对象的扩展

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
{
// es6简洁表达
let a = 1;
let b = 2;
let es5 = {
a:a,
b:b,
hello: function(){return 1},
};
let es6 ={
a,
b,
hello(){return 1},
};
}
{
// 属性表达式
let a = 'b';
let es5_obj = {
a:'c'
};
let es6_obj = {
[a]:'c' // 等同于 b:'c'
}
}
{
// 新增API
Object.is('abc','abc') // 比较两个对象是否相等
Object.is([],[]) // false,因为在内存中这是两个不同的引用, []===[]同理也是 false
Object.assign({a:'a'}, {b:'b'}) // {a:'a',b:'b'} 这是浅拷贝(只复制内存引用地址)
let test = {a:123, b:456};
for (let [key, value] of Object.entries(test)){
console.log(key,value)
}
}
{
// 扩展运算符
let {a,b,...c} = {a:'test', b:'kill', c:'ddd', d:"ccc"} // 跟数组差不多,但是现阶段支持不是太友好
}

Symbol

声明一个独一无二的值。(ES5 的对象属性名都是字符串,这容易造成属性名的冲突。比如,你使用了一个他人提供的对象,但又想为这个对象添加新的方法(mixin 模式),新方法的名字就有可能与现有方法产生冲突。如果有一种机制,保证每个属性的名字都是独一无二的就好了,这样就从根本上防止属性名的冲突。这就是 ES6 引入Symbol的原因。)

1
2
3
4
5
6
7
8
9
10
11
12
{
let a1 = Symbol.for('abc'); // for等于给一个symbol加了一个标识,再次.for('abc')就可以在其他地方引用此Symbol。
let obj = {
[a1]: '123',
'abc': 345,
c: 456
}
// symbol属性通过for in 和 let of 无法取到
// 可以通过 Object.getOwnPropertySymbols(obj).forEach(function(item){})
// 如果想把普通和Symbol都拿到:Reflect.ownKeys(obj).forEach(fn)
}

SET-MAP

  • set
  • map
  • WeakSet
  • WeakMap
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
{
// set
let list = new Set()
list.add(5);
list.add(7);
list.size // 2
let arr = [1,2,3,4,4];
let list1 = new Set(arr); // 数组去重
list1.size // 4
list.delete(5);
list.has(7)
list.clear();
// 下面三个相等
for (let key of list.keys()){}
for (let values of list.values()){}
for (let values of list){}
// 其他遍历方法
for (let [key, value] of list.entries()){}
list.forEach(fn(item))
}
{
// WeakSet (存储的数据类型只能是对象,并且是弱引用)
let weakList = new WeakSet();
let arg = {};
weakList.add(arg);
// 没有size,没有clear,不能遍历
}
{
// map 跟对象的区别是他的键可以是对象
let map = new Map();
let arr = ['123'];
map.set(arr, 456);
let map = new Map([['a',123], ['b',456]]) // {'a' => 123, 'b' => 456}
map.size // 2
map.delete('a');
map.clear();
// 遍历跟set一样
}
{
// WeakMap 的区别和map的区别基本一致
let o = {};
let weakMap = new WeakMap();
weakMap.set(o,123);
}

map-set 与 数组和对象的对比:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
// map && array
{
let map = new Map();
let array = []
// 增
map.set('a', 1);
array.push({a:1});
// 查
map.has('a'); // true
array.find( item => {item.a} ); // {a:1}
// 改
map.set('a',2);
array.forEach(item => item.a ? item.a = 2 : '');
// 删
map.delete('a');
array.splice(array.findIndex(item => item.a),1);
}
// set && array
{
let set = new Set();
let array = [];
// 增
set.add({t:1});
//数组不变,下面同理
// 查
set.has({t:1}); // false 因为引用地址不同
// 改
set.forEach(item => item.t ? item.t = 2 : '');
// 删
set.forEach(item => item.t ? set.delete(item) : '');
}
// map && set && object
{
let item = {t:1};
let map = new Map();
let set = new Set();
let obj = {};
// 增
map.set('t', 1);
set.add(item);
obj['t'] = 1;
// 查
map.has('t');
set.has(item);
't' in obj;
// 改
map.set('t', 2);
item.t = 2; // 改变原对象就直接改变了set里的数据
obj['t'] = 2;
// 删
map.delete('t');
set.delete(item);
delete obj['t'];
}
// 优先使用map,唯一性使用set。