偶然在项目中看见,感觉是重要的内容,先了解下基本语法,等有空再深入学习。
babel迷之安装 一觉醒来打开webstorm发现装上了Σ(っ °Д °;)っ
File Watcher打开添加babel时programa一栏填写:

$ProjectFileDir$/node_modules/.bin/babel

然后就能自动转码为ES5啦:)

1. 文档转换

Babel的REPL在线编译器,将ES6代码转为ES5代码。
https://babeljs.io/repl/

2. ES6部分特性

  1. var声明的内层变量会覆盖外层变量,而let提供块级作用域,变量只在代码块内有效。
  2. 当引用第三方库时声明的变量,用const来声明可以避免未来不小心重命名而导致出现bug
  3. 引入Class(类)概念,可以通过extends关键字实现继承。(这部分感觉有点像java)
  4. arrow function箭头函数的this是继承外层代码块的this`。
  5. template string,用反引号来标识起始,用${}来引用变量,而且所有的空格和缩进都会被保留在输出之中.
  6. destructuring解构:从数组和对象中提取值,对变量进行赋值。
  7. default默认值, rest语法(用Rest操作符以后,args参数就是一个数组了,任何操作数组的方法都可以直接对args使用)

电脑重装了,反正要重新配置环境,不如找个东西边学边装。就决定是你了,ES6!

  1. 惯例安装nodejs以及express
1
2
3
4
5
$ npm install express --save
$ npm install body-parser --save
$ npm install cookie-parser --save
$ npm install multer --save
$ npm list express

途中出现第一个问题,npm ERR! extraneoushttps://github.com/npm/npm/issues/10004#issuecomment-210710935,快捷方法是重装nodejs后用管理员模式安装>_o
第二个问题 express command not found ,解决方法https://stackoverflow.com/questions/23002448/express-command-not-found

1
npm install -g express-generator

  1. gulp
    文档
    1
    2
    3
    $ touch .babelrc

    $ touch gulpfile.babel.js

因为使用ES6语法,所以必须创建gulpfile.babel.js文件而不是gulpfile.js


然后又出现了很多问题,我就先去学习了gulp的详细用法,写了三篇文章总结。又学会了使用yeoman工具直接构建项目骨架。详细参见之前的博文。我发现webstorm里也可以直接选择yeoman构建,神器啊。
下面真的开始学习ES6语法了 O_<


参考阮一峰的《ECMAScript 6 入门》

1. let & const

1
2
3
4
5
6
7
function test(){
for(let i=1;i<3;i++){
console.log(i);
}
console.log(i);
}
test();
  1. 块作用域(大括号内)第二个console.log(i)脱离了块作用域,于是只能输出1,2。
  2. 严格模式:ES5代码中存在use strict来启动文件采用严格模式,ES6中则强制开启。严格模式中变量未声明则不能引用,会报错。
  3. 使用let时不能重复定义变量。
  4. 使用const声明的常量不能修改。
  5. 第4点注意情况
1
2
3
4
5
6
const PI =3.1415926;   //不能修改
const K ={
a:1
}
//K指向对象存储的指针,对象可变指针不变。
K.b = 3;

2. 解构赋值

代码

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
{
let a,b,rest;
[a,b]=[1,2];
console.log(a,b); //1,2
}

{
let a,b,rest;
[a,b,...rest]=[1,2,3,4,5,6];
console.log(a,b,rest); //1,2,(4) [3, 4, 5, 6]
}

{
let a,b;
({a,b}={a:1,b:2})
console.log(a,b); //1,2
}

{
let a,b,c,rest;
[a,b]=[1,2]
console.log(a,b,c); //1,2,undefined
}

{
let a,b,c,rest;
[a,b,c=3]=[1,2]
console.log(a,b,c); //1,2,3
}

//通过解构赋值实现变量交换,不需要中间变量。
{
let a=1;
let b=2;
[a,b]=[b,a];
console.log(a,b); //2,1
}

{
function f(){
return [1,2];
}
let a,b;
[a,b]=f();
console.log(a,b); //1,2
}

{
function f(){
return [1,2,3,4,5];
}
let a,b,c;
[a,,,b]=f(); //1,2,3,4 b对应4
console.log(a,b); //1,4
}

{
function f(){
return [1,2,3,4,5];
}
let a,b,c;
[a,...b]=f(); //取出第一个元素给a,其他都赋值给一个数组到b
console.log(a,b); //1,(4) [2, 3, 4, 5]
}

{
function f(){
return [1,2,3,4,5];
}
let a,b,c;
[a,,...b]=f();
console.log(a,b); //1,(3) [3, 4, 5]
}

{
let o= {p:42,q:true};
let {p,q}=o;
console.log(p,q); //42,true
}

{
let {a=10,b=5}={a:3};
console.log(a,b); //3,5
}

//嵌套对象和数组的应用
{
let metaData ={
title:'abc',
test:[{
title:'test',
desc:'description'
}]
}
let {title:esTitle,test:[{title:cnTitle}]}=metaData;
console.log(esTitle,cnTitle); //abc,test
}

3. 正则扩展

TBC

4. 字符串扩展

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
//unicode表示方法
{
console.log('a','\u0061'); //a,a
console.log('s','\u20BB7'); //s,₻7 因为编码超过0XFFFF,把20BB和7分别作为字符
console.log('s','\u{20BB7}'); //s 𠮷
}

{
let s = '𠮷'; //码值大于两个字节,此处为4字节。每两字节为一长度。
console.log('length',s.length); //length 2 es5中处理
console.log('0',s.charAt(0)); //0 � es5中取编码
console.log('1',s.charAt(1)); //1 �
console.log('at0',s.charCodeAt(0)); //at0,55362
console.log('at1',s.charCodeAt(1)); //at1,57271

let s1 = '𠮷a';
console.log('length',s1.length); //length 3
console.log('code0',s1.codePointAt(0)); //code0,134071 es6取字符码值(10进制)
console.log('code0',s1.codePointAt(0).toString(16)); //code0 20bb7,转换为16进制
console.log('code1',s1.codePointAt(1)); //code1,57271 与es5中一样取后两字节
console.log('code2',s1.codePointAt(2)); //code2,97 即取a
}

{
console.log(String.fromCharCode('0x20BB7')); //ஷ
console.log(String.fromCodePoint('0x20BB7')); //𠮷
}

{
let str ='\u{20BB7}abc';
for(let i=0;i<str.length;i++){
console.log('es5',str[i]);
} //es5 �,es5 �,es5 a,es5 b,es5 c
for(let code of str){ //字符串的遍历器接口,识别大于0xFFFF的码点
console.log('es6',code);
} //es6 𠮷,es6 a,es6 b,es6 c
}

{
let str='string';
console.log('includes',str.includes("r")); //includes,true
console.log('start',str.startsWith('str')); //start,true
console.log('end',str.endsWith('ing')); //end,true
}

{
let str='abc';
console.log(str.repeat(2)); //abcabc
}

{
let name ='list';
let info = 'hello world';
let m = `I am ${name},${info}`;
console.log(m); //I am list,hello world
}

{
console.log('1'.padStart(2,'0')); //01 长度为2,不够向前补第二个参数 可用在日期里
console.log('1'.padEnd(2,'0')); //10
}

{
let user = {
name:'list',
info:'hello world'
};
console.log(abc`i am ${user.name},${user.info}`); //i am ,,,listhello world
function abc(s,v1,v2){
console.log(s,v1,v2); //(3) ["i am ", ",", "", raw: Array(3)] "list" "hello world"
return s+v1+v2;
}
}

{
console.log(String.raw`Hi\n${1+2}`); //Hi\n3 String.raw方法而且对斜杠进行转义
console.log(`Hi\n${1+2}`); //Hi 换行 3
}

5. 数值扩展

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
{
console.log(0b111110111); //十进制503 es6中二进制都以0B开头(大小写都可)
console.log(0o767); //十进制503 es6中八进制都以0O开头
}

{
console.log('15',Number.isFinite(15)); //15 true
console.log('NaN',Number.isFinite(NaN)); //NaN false
console.log('1/0',Number.isFinite('true'/0)); //1/0 false
console.log('NaN',Number.isNaN(NaN)); //NaN true 判断是否非数字
console.log('NaN',Number.isNaN(0)); //NaN false 0是数字
}

{
console.log('25',Number.isInteger(25)); //25 true 判断是否是整数
console.log('25.0',Number.isInteger(25.0)); //25.0 true
console.log('25.1',Number.isInteger(25.1)); //25.1 false
console.log('25',Number.isInteger('25')); //25 false 接收参数必须是整数 -2^53-2^53区间内
}

{
console.log(Number.MAX_SAFE_INTEGER); //9007199254740991
console.log(Number.MIN_SAFE_INTEGER); //-9007199254740991
console.log('10',Number.isSafeInteger(10)); //10 true
console.log('a',Number.isSafeInteger('a')); //a false
}

{
console.log(4.1,Math.trunc(4.1)); //4.1 4 取整数部分
console.log(4.9,Math.trunc(4.9)); //4.9 4
}

{
console.log('-5',Math.sign(-5)); //-5 -1
console.log('0',Math.sign(0)); //0 0
console.log('5',Math.sign(5)); //5 1
console.log('50',Math.sign('50')); //50 1
console.log('foo',Math.sign('foo')); //foo NaN
}

{
console.log('-1',Math.cbrt(-1)); //-1 -1 立方根
console.log('8',Math.cbrt(8)); //8 2
}

6.数组扩展

问题:
.values is not a function
解决:
Uncaught TypeError: Object.values is not a function JavaScript
MDN文档Object.values()
需要import babel-polyfill,否则不兼容。

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
{
let arr = Array.of(3,4,7,9,11); //把一组数据变量转化为数据类型
console.log('arr=',arr); //arr= (5) [3, 4, 7, 9, 11]

let empty = Array.of();
console.log('empty=',empty); //empty= [] 不传参数,返回空数组
}

{
let p = document.querySelectorAll('p');
let pArr = Array.from(p); //把集合转换成数组
pArr.forEach(function(item){
console.log(item.textContent);
});

console.log(Array.from([1,3,5],function(item){return item*2;})); //(3) [2, 6, 10]
}

{
console.log('fill-7',[1,'a',undefined].fill(7)); //fill-7 (3) [7, 7, 7]
console.log('fill,pos',['a','b','c'].fill(7,1,3)); //fill,pos (3) ["a", 7, 7]
}

{
for(let index of ['1','c','ks'].keys()){
console.log('keys',index); //keys 0 keys 1 keys 2
}
for(let value of ['1','c','ks'].entries()){
console.log('entries',value); //entries (2) [0, "1"] entries (2) [1, "c"] entries (2) [2, "ks"]
}
for(let [index,value] of ['1','c','ks'].entries()){
console.log('entries',index,value); //entries 0 1 entries 1 c entries 2 ks
}
}

{
console.log([1,2,3,4,5].copyWithin(0,3,4));
}

{
console.log([1,2,3,4,5,6].find(function(item){return item>3})); //找出第一个符合的成员
console.log([1,2,3,4,5,6].findIndex(function(item){return item>3})); //找出第一个符合的成员的下标
}

{
console.log('number',[1,2,NaN].includes(1)); //number true 看数组中是否包括1
}

7. 函数扩展

函数新增特性:参数默认值;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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
{
function test(x,y = 'world'){
console.log('默认值',x,y);
}
test('hello'); //默认值 hello world
test('hello','u'); //默认值 hello u
}//y后面不能再加没有赋值的变量
//参数变量x是默认声明的,在函数体中,不能用let或const再次声明,否则会报错。

{
let x = 'test';
function test2(x,y=x){
console.log('作用域',x,y);
}
test2('cute'); //作用域 cute cute
test2(); //作用域 undefined undefined
}

{
let x = 'test';
function test2(c,y=x){
console.log('作用域',c,y);
}
test2('cute'); //作用域 cute test
}

{
function test3(...arg){
for(let v of arg){
console.log('rest',v);
}
}
test3(1,2,3,4,'a'); //rest 1;rest 2;rest 3;rest 4;rest 5;
}//rest参数(形式为...变量名),用于获取函数的多余参数,把他们都转换成数组

{
console.log(...[1,2,3]); //1 2 3 把数组转换成离散值
console.log('a',...[1,2,3]); //a 1 2 3
}

{
let arrow = v=>v*2;
let arrow2 = ()=>5;
console.log(arrow(3)); //6
console.log(arrow2()); //5
}//箭头函数: let函数名=函数参数=>函数返回值

{
function tail(x) {
console.log('tail',x);
}
function fx(x) {
return tail(x);
}
fx(123); //tail 123
}//尾调用 提升性能

8. 对象扩展

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
{
//简洁表示法
let o = 1;
let k = 2;
let es5 = {
o: o,
k: k
};
let es6 = {
o,
k
};
console.log(es5,es6); //{o: 1, k: 2} {o: 1, k: 2}

let es5_method = {
hello: function(){
console.log('hello');
}
};
let es6_method = {
hello(){
console.log('hello');
}
};
console.log(es5_method.hello(),es6_method.hello()); //hello;hello
}

{
//属性表达式
let a = 'b';
let es5_obj = {
a:'c',
b:'c'
};
//ES6允许字面量定义对象时,用表达式(放在方括号内)作为对象的属性名。
let es6_obj = {
[a]:'c'
};
console.log(es5_obj,es6_obj); //{a: "c", b: "c"} {b: "c"}
}

{
//新增API
console.log('字符串',Object.is('abc','abc'),'abc'==='abc'); //字符串 true true
console.log('数组',Object.is([],[]),[]===[]); //数组 false false 数组也是引用类型,地址不同不想等
}//Object.is功能等同===

{
console.log('拷贝',Object.assign({a:'a'},{b:'b'})); //拷贝 {a: "a", b: "b"}
} //Object.assign将源对象的所有可枚举属性(不拷贝继承属性),复制到目标对象(第一个参数)

{
let test = {k:123,o:456};
for(let [key,value] of Object.entries(test)){
console.log([key,value]);
} //(2) ["k", 123] ; (2) ["o", 456]
}//Object.entries遍历对象

9. Symbol用法

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
{
//Symbol声明变量独一无二
let a1=Symbol();
let a2=Symbol();
console.log(a1===a2); //false

let a3 = Symbol.for('a3');
let a4 = Symbol.for('a3');
console.log(a3===a4); //true
}

{
let a1 = Symbol.for('abc');
let obj = {
[a1]:'123',
'abc':345,
'c':456
};
console.log('obj',obj); //obj {abc: 345, c: 456, Symbol(abc): "123"}

for(let [key,value] of Object.entries(obj)){
console.log('let of',key,value); //let of abc 345; let of c 456
}

Object.getOwnPropertySymbols(obj).forEach(function(item){
console.log(obj[item]); //123
})

Reflect.ownKeys(obj).forEach(function(item){
console.log('ownKeys',item,obj[item]); //ownKeys abc 345;ownKeys c 456;ownKeys Symbol(abc) 123
})
}

10. set-map数据结构

优先使用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
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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
{
let list = new Set();
list.add(5);
list.add(7);
console.log('size',list.size); //size 2 类似数组中length
}

{
let arr = [1,2,3,4,5];
let list = new Set(arr); //转换数组为set集合
console.log('size',list.size); //size 5
}

{
let list = new Set();
list.add(1);
list.add(2);
list.add(1);
console.log('list',list); //list Set(2) {1, 2}

let arr = [1,2,3,1,2];
let list2 =new Set(arr);
console.log('list2',list2); //list2 Set(3) {1, 2, 3}

let arr2 = [1,2,3,1,'2'];
let list3 =new Set(arr2);
console.log('list3',list3); //list3 Set(4) {1, 2, 3, "2"}
}//该特性可以去除重复元素

{
let arr = ['add','delete','clear','has'];
let list = new Set(arr);

console.log('has',list.has('add')); //has true
console.log('delete',list.delete('add'),list); //delete true Set(3) {"delete", "clear", "has"}
list.clear();
console.log('list',list); //list Set(0) {}
}

{
let arr = ['add','delete','clear','has'];
let list = new Set(arr);

for(let key of list.keys()){
console.log('keys',key); //keys add;keys delete;keys clear;keys has
}
for(let value of list.values()){
console.log('value',value); //value add;value delete;value clear;value has
}
for(let value of list){
console.log('value',value); //value add;value delete;value clear;value has
}
for(let [key,value] of list.entries()){
console.log('entries',key,value); //entries add add;entries delete delete;entries clear clear;entries has has
}

list.forEach(function(item){
console.log(item); //add;delete;clear;has
})
}

{
let weakList = new WeakSet(); //元素只能是对象,弱引用 没有clear方法,set属性,不能遍历
let arg = {};
weakList.add(arg);
console.log('weakList',weakList); //weakList WeakSet {{…}}
}

{
let map = new Map();
let arr = ['123'];

map.set(arr,456);
console.log('map',map,map.get(arr)); //map Map(1) {Array(1) => 456} 456
}

{
let map = new Map([['a',123],['b',456]]);
console.log('map args',map); //map args Map(2) {"a" => 123, "b" => 456}
console.log('size',map.size); //size 2
console.log('delete',map.delete('a'),map); //delete true Map(1) {"b" => 456}
console.log('clear',map.clear(),map); //clear undefined Map(0) {}
}

{
let weakmap = new WeakMap();

let o ={};
weakmap.set(o,123);
console.log(weakmap.get(o)); //123
}

{
//数据结构横向对比,增删改查
let map = new Map();
let array = [];
//增
map.set('t',1);
array.push({t:1});
console.info('map array',map,array); //map array Map(1) {"t" => 1} [{…}]
//查
let map_exist = map.has('t');
let array_exist = array.find(item=>item.t);
console.info('map-array',map_exist,array_exist); //map-array true {t: 1}
//改
map.set('t',2);
array.forEach(item=>item.t?item.t=2:'');
console.info('map-array-modify',map,array); //map-array-modify Map(1) {"t" => 2} [{…}]
//删
map.delete('t');
let index = array.findIndex(item => item.t);
array.splice(index,1);
console.info('map array-empty',map,array); //map array-empty Map(0) {} []
}

{
//set和array对比
let set = new Set();
let array = [];
//增
set.add({t:1});
array.push({t:1});
console.info('set-array',set,array); //set-array Set(1) {{…}} [{…}]
//查
let set_exist = set.has({t:1});
let array_exist = array.find(item=>item.t);
console.info('set-array',set_exist,array_exist); //set-array false {t: 1}
//改
set.forEach(item=>item.t?item.t=2:'');
array.forEach(item=>item.t?item.t=2:'');
console.info('set-array-modify',set,array); //set-array-modify Set(1) {{…}}size: (...)__proto__: Set[[Entries]]: Array(1)0: Objectlength: 1 [{…}]
//删
set.forEach(item=>item.t?set.delete(item):'');
let index = array.findIndex(item => item.t);
array.splice(index,1);
console.info('set-array-empty',set,array); //set array-empty Set(0) {} []
}

{
//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;
console.info('obj-map-set',obj,map,set); //obj-map-set {t: 1} Map(1) {"t" => 1} Set(1) {{…}}
//查
console.info({
map_exist:map.has('t'),
set_exist:set.has(item),
obj_exist:'t' in obj
}); //{map_exist: true, set_exist: true, obj_exist: true}
//改
map.set('t',2);
item.t =2;
obj['t']= 2;
console.info('obj-map-set-modify',obj,map,set); //obj-map-set-modify {t: 2} Map(1) {"t" => 2} Set(1) {{…}}
//删除
map.delete('t');
set.delete(item);
delete obj['t'];
console.info('obj-map-set-empty',obj,map,set); //obj-map-set-empty {} Map(0) {} Set(0) {}
}

11. 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
110
111
112
{
let obj = {
time:'2017-11-17',
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-11-17
monitor.name ='new name';
console.log('set',monitor.time,monitor.name); //set 2018-11-17 new name
console.log('has','name' in monitor,'time' in monitor); //has true false
// delete monitor.time;
// console.log('delete',monitor); //Proxy {time: "2017-11-17", name: "new name", _r: 123}
// delete monitor._r;
// console.log('delete',monitor); //Proxy {time: "2017-11-17", name: "new name"}
console.log('ownKeys',Object.keys(monitor)); //ownKeys (2) ["name", "_r"]
}//类似供应商的原始数据对象,通过proxy代理商生成映射对象,用户访问后者

{
let obj = {
time:'2017-11-17',
name:'net',
_r:123
};

console.log('Reflect get',Reflect.get(obj,'time')); //Reflect get 2017-11-17
Reflect.set(obj,'name','new name');
console.log(obj); //{time: "2017-11-17", name: "new name", _r: 123}
console.log('has',Reflect.has(obj,'name')); //has true
}

//数据校验应用
{
function validator(target,validator){
//返回对target的代理,即对Person这个类的实例的代理
return new Proxy(target,{
_validator:validator,
set(target,key,value,proxy){
if(target.hasOwnProperty(key)){
let va = this._validator[key];
if(!!va(value)){
return Reflect.set(target,key,value,proxy);
}else{
throw Error(`不能设置${key}${value}`);
}
}else{
throw Error(`${key}不存在`);
}
}
});
}

const personValidators ={
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.info(person); //Proxy {name: "lilei", age: 30}
//因为代理限制所以不能随意赋值
//person.name =48; //Uncaught Error: 不能设置name 到48
person.name ='Han mei mei';
console.info(person); //Proxy {name: "Han mei mei", age: 30}
}

12. 类和对象

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

{
class Parent {
constructor(name = 'qq') {
this.name = name;
}
}

class Child extends Parent {

}

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

{
//继承传递参数
class Parent {
constructor(name = 'qq') {
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 = 'qq') {
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 mkqq
v.longName = 'hello';
console.log('setter', v.longName); //setter mkhello
}

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

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

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

13. 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
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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
{
//基本定义
let ajax = function(callback) {
console.log('execute');
setTimeout(function() {
callback && callback.call()
}, 1000);
};
ajax(function() {
console.log('timeout1');
});
} //先输出execute,1s后输出timeout1

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

ajax().then(function() {
console.log('promise', 'timeout2');
})
} //先输出timeout1,1s后输出promise timeout2

{
let ajax = function() {
console.log('execute3');
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');
})
}

{
let ajax = function(num) {
console.log('execute4');
return new Promise(function(resolve, reject) {
if (num > 5) {
resolve();
} else {
throw new Error('error!');
}
});
};

ajax(6).then(function() {
console.log('log', 6);
}).catch(function(err) {
console.log('catch', err);
})

ajax(3).then(function() {
console.log('log', 3);
}).catch(function(err) {
console.log('catch', err);
})
}

{
//所有图片加载完再加载页面
function loadImage(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 showImage(imgs) {
imgs.forEach(function(img) {
document.body.appendChild(img);
})
}

Promise.all([
loadImage('http://wx2.sinaimg.cn/mw690/6e67f96fgy1fkgeowvnqkj205606yjrh.jpg'),
loadImage('http://wx2.sinaimg.cn/mw690/6e67f96fgy1fkgeowvnqkj205606yjrh.jpg'),
loadImage('http://wx2.sinaimg.cn/mw690/6e67f96fgy1fkgeowvnqkj205606yjrh.jpg')
]).then(showImage)
}

{
//只要一张图片加载完就加载页面,其他不显示
function loadImage(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 showImage(img) {
let p = document.createElement('p');
p.appendChild(img);
document.body.appendChild(p);
}

Promise.race([
loadImage('http://wx2.sinaimg.cn/mw690/6e67f96fgy1fkgeowvnqkj205606yjrh.jpg'),
loadImage('http://wx2.sinaimg.cn/mw690/6e67f96fgy1fkgeowvnqkj205606yjrh.jpg'),
loadImage('http://wx2.sinaimg.cn/mw690/6e67f96fgy1fkgeowvnqkj205606yjrh.jpg')
]).then(showImage)
}

14. 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
41
42
43
44
45
46
{
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: undefined, done: true}
}

{
//自定义iterator 返回对象包括next方法和value,done值
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
}
}

{
let arr = ['hello', 'world'];
for (let value of arr) {
console.log('value', value); //value hello;value world
}
}

15. Genertor

报错:regeneratorRuntime is not defined
解决:transform-runtime,可以选择性加载babel插件。

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
{
//generator基本定义
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: true}
console.log(k.next()); //{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()); //{value: "A", done: false}
// console.log(status.next()); //{value: "B", done: false}
// console.log(status.next()); //{value: "C", done: false}
// console.log(status.next()); //{value: "A", done: false}
// console.log(status.next()); //{value: "B", done: false}
// }
//
// {
// let state = async function (){
// while(1){
// await 'A';
// await 'B';
// await 'C';
// }
// };
// let status =state();
// console.log(status.then()); //{value: "A", done: false}
// }

{
//制作抽奖按钮
let draw = function(count) {
//具体抽奖逻辑省略
console.info(`剩余${count}次`);
};

let residue = function*(count) {
while (count > 0) {
count--;
yield draw(count);
}
}
//次数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);
}

{
//长轮询
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.info('wait');
pull()
}, 1000);
} else {
console.info(d);
}
})
}
pull(); //如果code改成1则会开始长轮询输出wait
}

16. Decorators

修饰器是一个函数用来修改类的行为。

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
{
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);
// 第三方库修饰器的js库:core-decorators; npm install core-decorators
}

17. 模块化

18. 问题

描述:当使用import导入模块时,出现exports is not defined
1
2
3
4
5
6
7
//1、安装插件
npm install --save-dev babel-plugin-transform-es2015-modules-umd

//2、设置.babelrc配置文件
{
"plugins": ["transform-es2015-modules-umd"]
}