十一.Proxy和Reflect
Proxy保护对象不被外界访问;Object方法移植到Reflect
①Proxy:原始对象(供应商)通过Proxy(代理商)生成新对象(映射原对象),用户访问的是新对象,对新对象操作会通过Proxy传回原对象,原对象对用户不可见。
1 | { |
2 | let obj={ |
3 | time:'2017-03-11', |
4 | name:'net', |
5 | _r:123 |
6 | }; |
7 | let monitor=new Proxy(obj,{ |
8 | // 拦截对象属性的读取 |
9 | get(target,key){ |
10 | return target[key].replace('2017','2018') |
11 | }, |
12 | // 拦截对象设置属性 |
13 | set(target,key,value){ |
14 | if(key==='name'){ |
15 | return target[key]=value; |
16 | }else{ |
17 | return target[key]; |
18 | } |
19 | }, |
20 | // 拦截key in object操作 |
21 | has(target,key){ |
22 | if(key==='name'){ |
23 | return target[key] |
24 | }else{ |
25 | return false; |
26 | } |
27 | }, |
28 | // 拦截delete |
29 | deleteProperty(target,key){ |
30 | if(key.indexOf('_')>-1){ |
31 | delete target[key]; |
32 | return true; |
33 | }else{ |
34 | return target[key] |
35 | } |
36 | }, |
37 | // 拦截Object.keys,Object.getOwnPropertySymbols,Object.getOwnPropertyNames |
38 | ownKeys(target){ |
39 | return Object.keys(target).filter(item=>item!='time') |
40 | } |
41 | }); |
42 | console.log('get',monitor.time);//get 2018-03-11 |
43 | monitor.time='2018'; |
44 | monitor.name='mu'; |
45 | console.log('set',monitor.time,monitor);//set 2018-03-11 Proxy{time: "2017-03-11", name: "mu", _r: 123} |
46 | console.log('has','name' in monitor,'time' in monitor);//has true false time被隐藏了 |
47 | console.log('ownKeys',Object.keys(monitor));//ownKeys ["name", "_r"] time被隐藏了 |
48 | delete monitor._r; |
49 | console.log('delete',monitor);//Proxy{time: "2017-03-11", name: "mu"} |
50 | } |
②Reflect直接用
1 | { |
2 | let obj={ |
3 | time:'2018-11-27', |
4 | name:'net', |
5 | _r:123 |
6 | }; |
7 | console.log(Reflect.get(obj,'time'));//2018-11-27 |
8 | Reflect.set(obj,'name','muu'); |
9 | console.log(obj);//{time: "2018-11-27", name: "muu", _r: 123} |
10 | console.log(Reflect.has(obj,'name'));//ture |
11 | } |
十二.class
基本语法 类的继承 静态方法 静态属性 getter setter
1 | { |
2 | // 基本定义和生成实例 |
3 | class Parent{ |
4 | constructor(name='muu'){ |
5 | this.name=name; |
6 | } |
7 | } |
8 | let v_parent = new Parent('v'); |
9 | console.log('构造函数和实例',v_parent);//构造函数和实例 Parent {name: "v"} |
10 | } |
11 | { |
12 | // 继承 |
13 | class Parent{ |
14 | constructor(name='muu'){ |
15 | this.name=name; |
16 | } |
17 | } |
18 | class Child extends Parent{ |
19 | |
20 | } |
21 | console.log('继承',new Child());//继承 Child {name: "muu"} |
22 | } |
23 | { |
24 | // 继承传递参数 |
25 | class Parent{ |
26 | constructor(name='muu'){ |
27 | this.name=name; |
28 | } |
29 | } |
30 | class Child extends Parent{ |
31 | constructor(name='child'){ |
32 | super(name);//一定要放在构造函数第一行 |
33 | this.type='child'; |
34 | } |
35 | } |
36 | console.log('继承传递参数',new Child('hello'));//继承传递参数 Child {name: "hello", type: "child"} |
37 | } |
38 | { |
39 | // getter,setter |
40 | class Parent{ |
41 | constructor(name='muu'){ |
42 | this.name=name; |
43 | } |
44 | get longName(){ |
45 | return 'mu'+this.name |
46 | } |
47 | set longName(value){ |
48 | this.name=value; |
49 | } |
50 | } |
51 | let v=new Parent(); |
52 | console.log('getter',v.longName);//getter mumuu |
53 | v.longName='hello'; |
54 | console.log('setter',v.longName);//setter muhello |
55 | } |
56 | { |
57 | // 静态方法 |
58 | class Parent{ |
59 | constructor(name='muu'){ |
60 | this.name=name; |
61 | } |
62 | static tell(){ |
63 | console.log('tell'); |
64 | } |
65 | } |
66 | Parent.tell();//tell 通过类调用而不是通过实例调用 |
67 | } |
68 | { |
69 | // 静态属性 |
70 | class Parent{ |
71 | constructor(name='muu'){ |
72 | this.name=name; |
73 | } |
74 | static tell(){ |
75 | console.log('tell'); |
76 | } |
77 | } |
78 | Parent.type='test'; |
79 | console.log('静态属性',Parent.type);//静态属性 test |
80 | } |
十三.Promise
异步编程的解决方法,a执行完再执行b
优点:Promise可以异步执行多个,code简洁
1 | { |
2 | // 传统回调基本定义 打印执行,1秒后打印timeout1 |
3 | let ajax=function(callback){ |
4 | console.log('执行'); |
5 | setTimeout(function () { |
6 | callback&&callback.call() |
7 | }, 1000); |
8 | }; |
9 | ajax(function(){ |
10 | console.log('timeout1'); |
11 | }) |
12 | } |
13 | { |
14 | //打印执行2,1秒后打印promise timeout2 |
15 | let ajax=function(){ |
16 | console.log('执行2'); |
17 | return new Promise(function(resolve,reject){ |
18 | setTimeout(function () { |
19 | resolve() |
20 | }, 1000); |
21 | }) |
22 | }; |
23 | ajax().then(function(){//ajax()是一个promise实例,可有很多then方法 |
24 | console.log('promise','timeout2'); |
25 | }) |
26 | } |
27 | { |
28 | let ajax=function(num){ |
29 | console.log('执行3'); |
30 | return new Promise(function(resolve,reject){ |
31 | if(num>5){ |
32 | resolve() |
33 | }else{ |
34 | throw new Error('出错了') |
35 | } |
36 | }) |
37 | } |
38 | ajax(6).then(function(){//执行3 log 6 |
39 | console.log('log',6); |
40 | }).catch(function(err){ |
41 | console.log('catch',err); |
42 | }); |
43 | ajax(3).then(function(){//执行3 catch Error: 出错了 |
44 | console.log('log',3); |
45 | }).catch(function(err){ |
46 | console.log('catch',err); |
47 | }); |
48 | } |
十四.Iterator和for…of循环
①Iterator接口:用一种办法读取不同的数据集合(数组、Object、Map、Set)
1 | { |
2 | let arr=['hello','world']; |
3 | let map=arr[Symbol.iterator](); |
4 | console.log(map.next());//{value: "hello", done: false} |
5 | console.log(map.next());//{value: "world", done: false} |
6 | console.log(map.next());//{value: undefined, done: true} |
7 | } |
8 | { |
9 | //自定义读取 |
10 | let obj={ |
11 | start:[1,3,2], |
12 | end:[7,9,8], |
13 | [Symbol.iterator](){ |
14 | let self=this; |
15 | let index=0; |
16 | let arr=self.start.concat(self.end); |
17 | let len=arr.length; |
18 | return {//返回一个有next方法的对象 next(){ |
19 | if(index<len){ |
20 | return { |
21 | value:arr[index++], |
22 | done:false |
23 | } |
24 | }else{ |
25 | return { |
26 | value:arr[index++], |
27 | done:true |
28 | } |
29 | } |
30 | } |
31 | } |
32 | } |
33 | } |
34 | for(let key of obj){ |
35 | console.log(key);//1 3 2 7 9 8 |
36 | } |
37 | } |
②for…of不断调用Iterator
1 | { |
2 | //for...of 用法 |
3 | let arr=['hello','world']; |
4 | for(let value of arr){ |
5 | console.log(value);//hello world |
6 | } |
7 | } |
十五.Generator
异步编程,进入函数停在第一个yield前,执行一个next()方法,执行一个yield,直到没有可往下执行的yield或者return则返回done:true
1 | { |
2 | // genertaor基本定义 |
3 | let tell = function* (){ |
4 | yield 'a'; |
5 | yield 'b'; |
6 | return 'c' |
7 | }; |
8 | let k = tell(); |
9 | console.log(k.next());//{value: "a", done: false} |
10 | console.log(k.next());//{value: "b", done: false} |
11 | console.log(k.next());//{value: "c", done: true} |
12 | console.log(k.next());//{value: undefined, done: true} |
13 | } |
14 | { |
15 | //用genertaor部署,不手写Iterator(object对象不能用for...of除非有Iterator接口) |
16 | let obj={}; |
17 | obj[Symbol.iterator]=function* (){ |
18 | yield 1; |
19 | yield 2; |
20 | yield 3; |
21 | } |
22 | for(let value of obj){ |
23 | console.log(value);//1 2 3 |
24 | } |
25 | } |
26 | { |
27 | //状态机,可以不断查找状态 |
28 | let state = function* (){ |
29 | while(1){ |
30 | yield 'A'; |
31 | yield 'B'; |
32 | yield 'C'; |
33 | } |
34 | } |
35 | let status=state(); |
36 | console.log(status.next());//{value: "A", done: false} |
37 | console.log(status.next());//{value: "B", done: false} |
38 | console.log(status.next());//{value: "C", done: false} |
39 | console.log(status.next());//{value: "A", done: false} |
40 | console.log(status.next());//{value: "B", done: false} |
41 | } |
十六.Decorator
修饰器:函数修改类的行为
1 | { |
2 | //只读 |
3 | let readonly=function(target,name,descriptor){ |
4 | descriptor.writable=false; |
5 | return descriptor |
6 | }; |
7 | class Test{ |
8 | @readonly |
9 | time(){ |
10 | return '2018-11-27' |
11 | } |
12 | } |
13 | let test=new Test(); |
14 | console.log(test.time());//2018-11-27 |
15 | test.time=function(){ |
16 | console.log('reset time'); |
17 | }; |
18 | console.log(test.time());//2018-11-27 |
19 | } |
20 | { |
21 | let typename=function(target,name,descriptor){ |
22 | target.myname='hello'; |
23 | } |
24 | @typename//可以放class上面 |
25 | class Test{ |
26 | |
27 | } |
28 | console.log('类修饰符',Test.myname);//类修饰符 hello |
29 | //可引入第三方库修饰器的js库,不用自己写,直接@就可以:core-decorators; npm install core-decorators |
30 | } |
十七.模块化
1 | export let A=123; |
2 | export function test(){ |
3 | console.log('test'); |
4 | } |
5 | export class Hello{ |
6 | test(){ |
7 | console.log('class'); |
8 | } |
9 | } |
10 | import {A,test,Hello} from './xx';//{}中取什么写什么,./xx是上面内容的路径 |
11 | import *as lesson1 from './xx';//取所有内容放到对象lesson1中 |
12 | let A=123; |
13 | let test=function(){ |
14 | console.log('test'); |
15 | } |
16 | class Hello{ |
17 | test(){ |
18 | console.log('class'); |
19 | } |
20 | } |
21 | export default {A,test,Hello}//导出,但是我不指定名字,路径为./xxx |
22 | import lesson from './xxx';//我随便叫lesson,它接收了上面的内容 |
23 | console.log(lesson.A);//123 |