前言
ES6增加了不少新特性,下面继续整理了一下比较常用的新特性。
- Set
- Map
- Promise
- Class
- Module
Set
- Set类似于数组,但是成员的值都是唯一的,没有重复的值。
Set实例的增删改查方法
- add(value):添加某个值,返回 Set 结构本身。
- delete(value):删除某个值,返回一个布尔值,表示删除是否成功。
- has(value):返回一个布尔值,表示该值是否为Set的成员。
- clear():清除所有成员,没有返回值。
1 2 3 4 5 6 7 8 9 10 11 12
| { let arr=['add','delete','clear','has']; let list=new Set(arr);
console.log('has',list.has('add'));
console.log('delete',list.delete('add'),list); list.clear(); console.log('list',list); }
|
Set结构的实例有四个遍历方法,可以用于遍历成员。
keys():返回键名的遍历器
values():返回键值的遍历器
entries():返回键值对的遍历器
forEach():使用回调函数遍历每个成员
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
| { let arr=['add','delete','clear','has']; let list=new Set(arr);
for(let key of list.keys()){ console.log('keys',key); } for(let value of list.values()){ console.log('value',value);
} for(let [key,value] of list.entries()){ console.log('entries',key,value);
}
list.forEach(function(item){console.log(item);}) }
|
去除数组的重复成员
1 2 3 4 5 6 7
| { let arr = [1,2,3,3,5,4,4,5]; let list = new Set(arr);
console.log(list); }
|
Map
- JavaScript 的对象(Object),本质上是键值对的集合(Hash结构),但是传统上只能用字符串当作键。这给它的使用带来了很大的限制。
- ES6 提供了 Map 数据结构。它类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。
- Object 结构提供了“字符串—值”的对应,Map 结构提供了“值—值”的对应
- 如果你需要“键值对”的数据结构,Map 比 Object 更合适。
1 2 3 4 5 6 7 8 9
| { let map = new Map(); let arr=['123'];
map.set(arr,456);
console.log('map',map,map.get(arr)); }
|
Map 结构的实例有以下属性和操作方法。
- size属性返回 Map 结构的成员总数。
- set方法设置键名key对应的键值为value,然后返回整个 Map结构。如果key已经有值,则键值会被更新,否则就新生成该键。set方法返回的是当前的Map对象,因此可以采用链式写法。
- get方法读取key对应的键值,如果找不到key,返回undefined。
- has方法返回一个布尔值,表示某个键是否在当前 Map 对象之中。
- delete方法删除某个键,返回true。如果删除失败,返回false。
- clear方法清除所有成员,没有返回值。
Map的遍历方法同Set
Map Set Array Object数据结构对比
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
| { let map=new Map(); let array=[]; map.set('t',1); array.push({t:1});
console.info('map-array',map,array);
let map_exist=map.has('t'); let array_exist=array.find(item=>item.t); console.info('map-array',map_exist,array_exist);
map.set('t',2); array.forEach(item=>item.t?item.t=2:''); console.info('map-array-modify',map,array);
map.delete('t'); let index=array.findIndex(item=>item.t); array.splice(index,1); console.info('map-array-empty',map,array); }
|
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
| { let set=new Set(); let array=[];
set.add({t:1}); array.push({t:1});
console.info('set-array',set,array);
let set_exist=set.has({t:1}); let array_exist=array.find(item=>item.t); console.info('set-array',set_exist,array_exist);
set.forEach(item=>item.t?item.t=2:''); array.forEach(item=>item.t?item.t=2:''); console.info('set-array-modify',set,array);
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); }
|
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
| { 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('map-set-obj',obj,map,set);
console.info({ map_exist:map.has('t'), set_exist:set.has(item), obj_exist:'t' in obj })
map.set('t',2); item.t=2; obj['t']=2; console.info('map-set-obj-modify',obj,map,set);
map.delete('t'); set.delete(item); delete obj['t']; console.info('map-set-obj-empty',obj,map,set); }
|
建议性总结
- 能使用map,就不使用数组和object,如需保证数据的唯一性,考虑使用set。
Promise
Promise 是异步编程的一种解决方案
- 对象的状态不受外界影响。
Promise
对象的三种状态:pending
(进行中)、fulfilled
(已成功)和rejected
(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。
- 一旦状态改变,就不会再变,任何时候都可以得到这个结果。
- Promise 实例具有
then
方法, then
方法的第一个参数是resolved
状态的回调函数,第二个参数(可选)是rejected
状态的回调函数。
ES5异步写法与ES6的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
| { let ajax=function(callback){ console.log('ES5执行'); setTimeout(function () { callback&&callback.call() }, 1000); }; ajax(function(){ console.log('ES5:timeout'); }) }
{ let ajax=function(){ console.log('执行2'); return new Promise(function(resolve,reject){ setTimeout(function () { resolve() }, 1000); }) };
ajax().then(function(){ console.log('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'); }) }
|
- Promise 新建后立即执行,然后
then
方法指定的回调函数,将在当前脚本所有同步任务执行完才会执行。
- 从上面的例子可以看出,相对于ES5而言,ES6的Promise避免了回调地狱,并且代码阅读性很高,后期维护可以很轻松看清楚异步函数的先后顺序。
catch
Promise.prototype.catch
方法是.then(null, rejection)
的别名,用于指定发生错误时的回调函数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| { 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); });
ajax(3).then(function(){ console.log('log',3); }).catch(function(err){ console.log('catch',err); }); }
|
all
Promise.all
方法创建的实例只有在接收的参数状态全部为fulfilled
时, Promise.all
方法包装的实例才会变为fulfilled
, 或者之中有一个被rejected
,该实例才会变为rejected
。此时第一个被reject
的实例的返回值,会传递给Promise.all
方法创建实例的回调函数。
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
| { 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); }) }
Promise.all([ loadImg('2.png'), loadImg('ba.png'), loadImg('c.png') ]).then(showImgs)
}
|
race
Promise.race
方法的参数与Promise.all
方法一样,如果不是 Promise 实例,就会先调用Promise.resolve
方法,将参数转为 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
| { 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(img){ let p=document.createElement('p'); p.appendChild(img); document.body.appendChild(p) }
Promise.race([ loadImg('32.png'), loadImg('a.png'), loadImg('bc.png') ]).then(showImgs)
}
|
Class
- ES6 的
class
可以让对象原型的写法更加清晰、更像面向对象编程的语法。
- Class 可以通过
extends
关键字实现继承,这比 ES5 的通过修改原型链实现继承,要清晰和方便很多。
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
| { class Parent{ constructor(name='wang'){ this.name=name; } } let v_parent=new Parent('v'); console.log('构造函数和实例',v_parent); }
{ class Parent{ constructor(name='wang'){ this.name=name; } }
class Child extends Parent{
}
console.log('继承',new Child()); }
{ class Parent{ constructor(name='wang'){ this.name=name; } }
class Child extends Parent{ constructor(name='child'){ this.color = "color"; super(name); this.type='child'; } }
console.log('继承传递参数',new Child('hello')); }
|
ES5 的继承,实质是先创造子类的实例对象this
,然后再将父类的方法添加到this
上面(Parent.apply(this)
)。ES6 的继承机制完全不同,实质是先将父类实例对象的属性和方法,加到this
上面(所以必须先调用super
方法),然后再用子类的构造函数修改this
。
与 ES5 一样,在“类”的内部可以使用get
和set
关键字,对某个属性设置存值函数和取值函数,拦截该属性的存取行为。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| { class Parent{ constructor(name='wang'){ this.name=name; }
get longName(){ return 'mk'+this.name }
set longName(value){ this.name=value; } }
let v=new Parent(); console.log('getter',v.longName); v.longName='hello'; console.log('setter',v.longName); }
|
类相当于实例的原型,所有在类中定义的方法,都会被实例继承。如果在一个方法前,加上static
关键字,就表示该方法不会被实例继承,而是直接通过类来调用,这就称为“静态方法”。
如果静态方法包含this
关键字,这个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
| { class Parent{ constructor(name='wang'){ this.name=name; }
static tell(){ console.log('tell'); } }
Parent.tell();
}
{ class Parent{ constructor(name='wang'){ this.name=name; }
static tell(){ console.log('tell'); } }
Parent.type='test';
console.log('静态属性',Parent.type);
}
|
Module模块化
模块功能主要由两个命令构成:export
和import
。export
命令用于规定模块的对外接口,import
命令用于输入其他模块提供的功能。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| let A=123; let test=function(){ console.log('test'); } class Hello{ test(){ console.log('class'); } }
export default { A, test, Hello }
import Module from '../Module.js';
|
参考
阮一峰 ECMAScript 6 入门
感谢打赏,错误之处欢迎指正交流(`・ω・´) !~~
微信打赏
支付宝打赏