ES6的迁移之路---[5]

前言

对ES6中的ProxyClassPromiseiteratorgenertaor修饰器import进行学习笔记

Proxy

Proxy(代理) 是 ES6 中新增的一个特性。
Proxy 让我们能够以简洁易懂的方式控制外部对对象的访问。

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
{
let obj={
time:'2017-03-11',
name:'net',
_r:123
};
let monitor=new Proxy(obj,{
// 拦截对象属性的读取
get(target,key){
return target[key].replace('2017','2018')
},
// 拦截对象设置属性
set(target,key,value){
if(key==='name'){
return target[key]=value;
}else{
return target[key];
}
},
// 拦截key in object操作
has(target,key){
if(key==='name'){
return target[key]
}else{
return false;
}
},
// 拦截delete
deleteProperty(target,key){
if(key.indexOf('_')>-1){
delete target[key];
return true;
}else{
return target[key]
}
},
// 拦截Object.keys,Object.getOwnPropertySymbols,Object.getOwnPropertyNames
ownKeys(target){
return Object.keys(target).filter(item=>item!='time')
}
})
console.log('get',monitor.time);//get 2018-03-11

monitor.time='2018';
monitor.name='mukewang';
console.log('set',monitor.time);set 2018-03-11

console.log('has','name' in monitor,'time' in monitor);//has true false
console.log('ownKeys',Object.keys(monitor));//ownKeys ["name",'_r']
}

Class

Class这个概念,作为对象的模板,通过class关键字,可以定义类。基本上,ES6的class可以看作只是一个语法糖,它的绝大部分功能,ES5都可以做到,新的class写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已

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
{
// 基本定义和生成实例
class Parent{
constructor(name='mukewang'){
this.name=name;
}
}
let v_parent=new Parent('v');
console.log('构造函数和实例',v_parent);//构造函数和实例 Parent { name: 'v' }
}

{
// 继承
class Parent{
constructor(name='mukewang'){
this.name=name;
}
}

class Child extends Parent{

}

console.log('继承',new Child());继承 Child { name: 'mukewang' }
}

{
// 继承传递参数
class Parent{
constructor(name='mukewang'){
this.name=name;
}
}

class Child extends Parent{
constructor(name='child'){
super(name);
this.type='child';
}
}

console.log('继承传递参数',new Child('hello'));//继承传递参数 Child { name: 'hello', type: 'child' }
}

{
// getter,setter
class Parent{
constructor(name='mukewang'){
this.name=name;
}

get longName(){
return 'mk'+this.name
}

set longName(value){
this.name=value;
}
}

let v=new Parent();
console.log('getter',v.longName);//getter mkmukewang
v.longName='hello';
console.log('setter',v.longName);//setter mkhello
}

{
// 静态方法
class Parent{
constructor(name='mukewang'){
this.name=name;
}

static tell(){
console.log('tell');
}
}

Parent.tell();//test

}

{
// 静态属性
class Parent{
constructor(name='mukewang'){
this.name=name;
}

static tell(){
console.log('tell');
}
}
Parent.type='test';
console.log('静态属性',Parent.type);//静态属性 test
}

Promise

Promise 是异步编程的一种解决方案,比传统的解决方案–回调函数和事件--更合理和更强大。它由社区最早提出和实现,ES6将其写进了语言标准,统一了语法,原生提供了Promise

所谓Promise ,简单说就是一个容器,里面保存着某个未来才回结束的事件(通常是一个异步操作)的结果。从语法上说,Promise是一个对象,从它可以获取异步操作的消息。
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
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
{
// 基本定义
let ajax=function(callback){
console.log('执行');
setTimeout(function () {
callback&&callback.call()
}, 1000);
};
ajax(function(){
console.log('timeout1');
}) // 执行 timeout1

}

{
let ajax=function(){
console.log('执行2');
return new Promise(function(resolve,reject){
setTimeout(function () {
resolve()
}, 1000);
})
};

ajax().then(function(){
console.log('promise','timeout2');
})//执行2 promise timeout2

}

{
let ajax=function(){
console.log('执行3');
return new Promise(function(resolve,reject){
setTimeout(function () {
resolve()
}, 1000);
})
};

ajax()
.then(function(){
return new Promise(function(resolve,reject){
setTimeout(function () {
resolve()
}, 2000);
});
})
.then(function(){
console.log('timeout3');//执行3 timeout3

})
}

{
let ajax=function(num){
console.log('执行4');
return new Promise(function(resolve,reject){
if(num>5){
resolve()
}else{
throw new Error('出错了')
}
})
}

ajax(6).then(function(){
console.log('log',6);
}).catch(function(err){
console.log('catch',err);
});//执行4 log6

ajax(3).then(function(){
console.log('log',3);
}).catch(function(err){
console.log('catch',err);
});//执行4 error
}

下面是一个用Promise对象实现的 Ajax 操作的例子。

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
const getJSON = function(url) {
const promise = new Promise(function(resolve, reject){
const handler = function() {
if (this.readyState !== 4) {
return;
}
if (this.status === 200) {
resolve(this.response);
} else {
reject(new Error(this.statusText));
}
};
const client = new XMLHttpRequest();
client.open("GET", url);
client.onreadystatechange = handler;
client.responseType = "json";
client.setRequestHeader("Accept", "application/json");
client.send();

});

return promise;
};

getJSON("/posts.json").then(function(json) {
console.log('Contents: ' + json);
}, function(error) {
console.error('出错了', error);
});

深入理解Promise.all()
我们在来看一下这段代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Promise.all([asyncTask(1),asyncTask(2),asyncTask(3)])
.then(resultList => {
console.log('results:',resultList);
});
传入3个Promise实例:
Promise.all([
new Promise(function(resolve, reject) {
resolve(1)
}),
new Promise(function(resolve, reject) {
resolve(2)
}),
new Promise(function(resolve, reject) {
resolve(3)
})
]).then(arr => {
console.log(arr) // [1, 2, 3]
})

Promise.race()
语法和all()一样,但是返回值有所不同,race根据传入的多个Promise实例,只要有一个实例resolve或者reject,就只返回该结果,其他实例不再执行。

1
2
3
4
5
6
7
8
9
10
11
12
13
Promise.race([
new Promise(function(resolve, reject) {
setTimeout(() => resolve(1), 1000)
}),
new Promise(function(resolve, reject) {
setTimeout(() => resolve(2), 100)
}),
new Promise(function(resolve, reject) {
setTimeout(() => resolve(3), 10)
})
]).then(value => {
console.log(value) // 3
})

iterator

遍历器(Iterator)就是这样一种机制。它是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署Iterator接口,就可以完成遍历操作(即依次处理该数据结构的所有成员)。
作用:

为各种数据结构,提供一个统一的、简便的访问接口
使得数据结构的成员能够按某种次序排列
ES6创造了一种新的遍历命令for…of循环,Iterator接口主要供for…of消费
Iterator的遍历过程:

  • 创建一个指针对象,指向当前数据结构的起始位置。也就是说,遍历器对象本质上,就是一个指针对象。
  • 第一次调用指针对象的next方法,可以将指针指向数据结构的第一个成员。
  • 第二次调用指针对象的next方法,指针就指向数据结构的第二个成员。
  • 不断调用指针对象的next方法,直到它指向数据结构的结束位置。
1
2
3
4
5
6
7
8
9
10
11
12
{
let arr=['hello','world'];
let map=arr[Symbol.iterator]();
console.log(map.next());
console.log(map.next());
console.log(map.next());
}
/*
{ value: 'hello', done: false }
{ value: 'world', done: false }
{ value: undefined, done: true }
*/

自定义for of 循环

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
{
let obj={
start:[1,3,2],
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
Generator函数是ES6提供的一种异步编程解决方案,语法行为与传统函数完全不同。
Generator函数有多种理解角度。从语法上,首先可以把它理解成,Generator函数一个状态机,封装了多个内部状态。
执行Generator函数会返回一个遍历器对象,也就是说,Generator函数除了状态机,还是一个遍历器对象生成函数。
形式上,Generator函数是一个普通函数,但是有两个特征。一是,function关键字与函数名之间有一个星号,二是,函数体内部使用yield语句,定义不同的内部状态。(yield语句在英语里的意思就是“产出”)

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
{
// genertaor基本定义
let tell=function* (){
yield 'a';
yield 'b';
return 'c'
};

let k=tell();

console.log(k.next());
console.log(k.next());
console.log(k.next());
console.log(k.next());
}
/*
{ value: 'a', done: false }
{ value: 'b', done: false }
{ value: 'c', done: true }
{ value: undefined, done: true }
*/

{
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
*/
}

{
let state=function* (){
while(1){
yield 'A';
yield 'B';
yield 'C';
}
}
let status=state();
console.log(status.next());
console.log(status.next());
console.log(status.next());
console.log(status.next());
console.log(status.next());
/*
{ value: 'A', done: false }
{ value: 'B', done: false }
{ value: 'C', done: false }
{ value: 'A', done: false }
{ value: 'B', done: false }
*/
}

修饰器(descriptor)

decorator是ES7引入的功能,它是一个函数,用来修改类甚至于是方法的行为。

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
{
let readonly=function(target,name,descriptor){
descriptor.writable=false;
return descriptor
};

class Test{
@readonly
time(){
return '2017-03-11'
}
}

let test=new Test();

// test.time=function(){
// console.log('reset time');
// };

console.log(test.time());
}
{
let typename=function(target,name,descriptor){
target.myname='hello';
}

@typename
class Test{

}

console.log('类修饰符',Test.myname);//'hello'
// 第三方库修饰器的js库:core-decorators; npm install core-decorators
}

import

import语句用于导入由另一个模块导出的绑定。
创建a.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
let A=123;
let test=function(){
console.log('test');
}
class Hello{
test(){
console.log('class');
}
}

export default {
A,
test,
Hello
}

b.js

1
2
3
4
import a from "./a.ja"
console.log(a.A) // 123
a.test()// 'test'
new a.Hello().test() // 'class'

本文标题:ES6的迁移之路---[5]

文章作者:NoHomeMan

发布时间:2018年10月23日 - 16:10

最后更新:2018年10月23日 - 17:10

原始链接:http://nohomeman.github.io/ES6的迁移之路-5/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

-------------The End-------------