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

Proxy和Reflect

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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
// Proxy
{
let obj = {
time: '2017-03-11',
name: 'net',
_r: 213
};
// 通过一个代理来操作对象
let monitor = new Proxy(obj,{
// 拦截对象属性的读取(可以进行一定的操作,但是不影响原对象)
get(target, key){
return target[key].replace('2017', '2018');
},
// 拦截对象的设置
set(target, key, value){
// 只允许修改name
if (key === 'name') {
return target[key] = value;
}else{
return target[key];
}
},
// 拦截判断
has(target, key){
// 只暴露name
if (key === 'name'){
return target[key]
}else{
return false;
}
},
// 拦截删除
deleteProperty(target, key){
// 只能删除下划线开头的属性
if (key.indexOf('_') == 0){
delete target
}
},
// 拦截Obeject.keys, Object.getOwnPropertySymbols,Object.getOwnPropertyNames
ownKeys(target){
// 保护time属性
return Object.keys(target).filter(item => item!= 'time')
}
});
monitor.time // 2018-03-11
time in monitor // false
}
// Reflect
{
let obj = {
time: '2017-03-11',
name: 'net',
_r: 213
};
// Reflect跟Proxy的方法是一样的
Reflect.get(obj, 'time') // 2017-03-11
Reflect.set(obj, 'name', 'newname')
Reflect.has(obj, 'name')
}
// 例子(解耦验证)
{
// 传入一个对象和验证器
function validator(target, validator){
return new Proxy(target, {
_validator: validator,
set(target, key, value, proxy){
if (target.hasOwnProperty(key)){
let va = this._validator[key];
if (!!va(value)){
// var a; b=!!a; a默认是undefined。!a是true,!!a则是false,所以b的值是false,而不再是undefined,也非其它值,主要是为后续判断提供便利。
return Reflect.set(target, key, value, proxy)
}else{
throw Error(`不能设置${key}${value}`);
}
}else{
throw Error(`${key}不存在`)
}
}
})
}
// 验证器
const perValidators = {
name(val){
return typeof val === 'string'
},
age(val){
return typeof val === 'number' && val > 18
}
}
// 对象
class Person{
constructor(name, age){
this.name = name;
this.age = age;
return validator(this, personValidators)
}
}
const person = new Person('lilei', 30);
console.log(person) // {name:'lilei', age:'30'};
const person = new Person('lilei', 15);
console.log(person) // 报错,不能设置age到15
// 这样的好处就是条件和对象完全分离,可细细体会。
}

类和对象

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
{
// 基本定义和生成实例
class Parent{
constructor( name = "default" ){
this.name = name;
}
// getter 和 setter, 在赋值和取值时可以进行一定操作
get longName(){
return 'test' + this.name
}
set longName(){
this.name = value
}
// 静态方法
static tell(){
console.log('tell')
}
}
Parent.age = 18; //静态属性
let v_parent = new Parent('v');
console.log('构造函数和实例', v_parent); // {name: v, age = 18}
// 继承
class Child extends Parent{
constructor(name = 'child'){
super(name); // super 其实就是父类的构造函数 , 另外super需要放在第一行
this.type = 'child';
}
}
console.log(new Child()); // {name: default, age = 18}
}

Promise

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
{
// 异步解决方案
// 基本结构
let ajax = function(num){
console.log('test');
return new Promise(function(resolve, reject){
if(num > 5){
resolve();
}else{
throw new Error('出错')
}
})
}
ajax(6).then(function(){
console.log('good');
}).catch(function(err){
console.log('catch',err)
})
// 基本使用例子
function loadImg(src){
return new Promise((resolve, reject) => {
let img = document.createElement('img');
img.src = src;
img.onload = function(){
resolve(img);
}
img.onerror = function(err){
reject(err);
}
})
}
function showImgs(imgs){
imgs.forEach(function(img){
document.body.appendChild(img);
})
}
// 必须三张图片都加载完再执行then
Promise.all([
loadImg('http://i4.buimg.com/567571/dasdasd.png'); loadImg('http://i4.buimg.com/567571/dasdasd.png');
loadImg('http://i4.buimg.com/567571/dasdasd.png');
]).then(showImgs);
// 只完成一个就执行then,并且不执行其他的了
Promise.race([
loadImg('http://i4.buimg.com/567571/dasdasd.png'); loadImg('http://i4.buimg.com/567571/dasdasd.png');
loadImg('http://i4.buimg.com/567571/dasdasd.png');
]).then(showImgs);
}

Iterator 和 for of 循环

for of 是专门针对具有Iterator接口的数据结构来读取数据。

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
// 数组
{
let arr = ['hello', 'world'];
let map = arr[Symbol.iterator]();
console.log(map.next()); // {value: 'hello', done: false}
console.log(map.next()); // {value: 'world', done: false}
console.log(map.next()); // {value: undifined, done: false}
}
// 自定义Iterator接口
{
let obj = {
start: [1,2,3],
end: [7,9,8],
[Symbol.iterator](){
let self = this;
let index = 0;
let arr = self.start.concat(self.end);
let len = arr.length;
return {
next(){
if (index < len){
return {
value: arr[index++],
done: false
}
}else{
return {
value: arr[index++],
done: true
}
}
}
}
}
}
for (let key of obj){
console.log(key); // 1 3 2 7 9 8
}
}

Generator

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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
// 基本用法
{
let tell = function* (){
yield 'a';
yield 'b';
return c;
}
let k = tell();
console.log(k.next()); // {value: 'a', done: false}
console.log(k.next()); // {value: 'b', done: false}
console.log(k.next()); // {value: 'c', done: false}
console.log(k.next()); // {value: undefined, done: true}
}
// 使用generator至少iterator接口
{
let obj = {};
obj[Symbol.iterator] = function*(){
yield 1;
yield 2;
yield 3;
}
for (let value of obj){
console.log('value', value); // value 1 value 2 value 3
}
}
// Generator适用场景之状态机
{
let state = function*(){
while(1){
yield 'A';
yield 'B';
yield 'C';
}
}
}
// 实例1 - 次数限制
{
let draw = function(count){
console.log('剩余${count}次')
}
let residue = function*(count){
while (count > 0){
count --;
yield draw(count);
}
}
let star = residue(5);
let btn = document.createElement('button');
btn.id = 'start';
btn.textContent = '抽奖';
document.body.appendChild(btn);
document.getElementById('start').addEventListener('click', function(){
star.next();
},false);
}
// 实例2 - 长轮询
{
let ajax = function* (){
yield new Promise(function(resolve, reject){
setTimeout(function() {
resolve({code: 0})
}, 200)
})
}
let pull = function(){
let generator = ajax();
let step = generator.next();
step.value.then(function(d){
if (d.code != 0){
setTimeout(function(){
console.log('wait');
pull();
},1000)
}else{
console.log(d)
}
})
}
}