一、let和const
es6之前有兩個(gè)作用域:全局作用域、函數(shù)作用域
es6新增加了塊作用域,也就是{}包起來(lái)的代碼
function test() {
for (let i=1;i<3;i++){
console.log(i);
}
console.log(i);//error: i is not defined
}
為什么報(bào)錯(cuò)?因?yàn)閑s6強(qiáng)制開(kāi)啟了嚴(yán)格模式,變量未聲明不能引用
let a=3;
let a=4;
報(bào)錯(cuò),不能重復(fù)聲明!
const PI=3.14;
定義常量,常量不能修改!也是有塊作用域的!并且,聲明的時(shí)候必須賦值!
const PI=3.14,
k={
a:1
};
k.b=3;
console.log(PI,k);
可以輸出。是因?yàn)閗是對(duì)象,是引用類型,返回的是對(duì)象存儲(chǔ)內(nèi)存的指針,發(fā)生了修改也可以輸出。
const和let的唯一區(qū)別就是,const不可以被更改,所以當(dāng)聲明變量的時(shí)候,尤其是在聲明容易被更改的全局變量的時(shí)候,盡量使用const。
- 更好的代碼語(yǔ)義化,一眼看到就是常量。
- 另一個(gè)原因是因?yàn)镴avaScript 編譯器對(duì)const的優(yōu)化要比let好,多使用const,有利于提高程序的運(yùn)行效率。
- 所有的函數(shù)都應(yīng)該設(shè)置為常量。
二、解構(gòu)賦值
解構(gòu)賦值的分類:數(shù)組結(jié)構(gòu)賦值(左右都是數(shù)組)、對(duì)象結(jié)構(gòu)賦值(左右都是對(duì)象)、字符串結(jié)構(gòu)賦值(左數(shù)組、右字符串)、布爾值結(jié)構(gòu)賦值、函數(shù)參數(shù)解構(gòu)賦值(數(shù)組解構(gòu)賦值在函數(shù)上的引用)、數(shù)值解構(gòu)賦值
{
let a,b,rest;
[a, b]=[1,2];
console.log(a);//1
console.log(b);//2
}
{
let a,b,rest;
[a, b, ...rest]=[1,2,3,4,5,6];
console.log(a, b, rest);//1 2 [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,c = 3]=[1,2];
console.log(a, b, c);//1 2 3
}
如果c沒(méi)有賦值,找不到可以配對(duì)的值,c就是undifined。
適用場(chǎng)景:變量交換,選擇性獲取返回值
{
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();//1 2
}
{
function f1() {
return [1,2,3,4,5];
}
let a,b,c;
[a, , ,b]=f1();
console.log(a, b);//1 4
}
{
function f1() {
return [1,2,3,4,5];
}
let a,b,c;
[a,...b]=f1();
console.log(a, b);//1 [2,3,4,5]
}
上面這兩種也可以混合使用。
在用到數(shù)組成員對(duì)變量賦值時(shí),盡量使用解構(gòu)賦值。
對(duì)象的解構(gòu)賦值::
{
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 a=10是默認(rèn)值,找不到匹配項(xiàng)時(shí)才=10
}
使用場(chǎng)景:
{
let metaData={
title: 'abc',
test: [{
title: 'test',
desc: 'description'
}]
};
let {title:esTitle,test:[{title:cnTitle}]} = metaData;
console.log(esTitle,cnTitle);//abc test
}
函數(shù)的參數(shù)如果是對(duì)象的成員,優(yōu)先使用解構(gòu)賦值。
如果函數(shù)返回多個(gè)值,優(yōu)先使用對(duì)象的解構(gòu)賦值,而不是數(shù)組的解構(gòu)賦值。這樣便于以后添加返回值,以及更改返回值的順序。
三、正則擴(kuò)展
正則新增特性:u修飾符、y修飾符、s修飾符
{
//es5
let regex=new RegExp('xyz','i');
let regex2=new RegExp(/xyz/i);//或者直接/xyz/i
console.log(regex.test('xyz123'));//true
console.log(regex2.test('xyz123'));//true
//es6,參數(shù)可以下面這樣
let regex3=new RegExp(/xyz/ig,'i');
console.log(regex3.flags);//i 即第二個(gè)參數(shù)的修飾符會(huì)覆蓋前面正則表達(dá)式的修飾符
}
{
//y修飾符 vs g修飾符
let s='bbb_bb_b';
let a1=/b+/g;
let a2=/b+/y;
console.log('one',a1.exec(s),a2.exec(s));//bbb bbb
console.log('two',a1.exec(s),a2.exec(s));//bb null
//相同點(diǎn):都是全局匹配
//不同點(diǎn):g是上一次匹配的下一個(gè)字符開(kāi)始,即_,不強(qiáng)調(diào)在第一個(gè)字符就能匹配上
//不同點(diǎn):y是上一次匹配的下一個(gè)字符開(kāi)始,即_,但是必須得在第一個(gè)字符就能匹配上
console.log(a1.sticky,a2.sticky);//false true 是否開(kāi)啟y
}
{
//u修飾符:unicode
console.log('u-1',/^\uDB3D/.test('\uDB3D\uDC2A'));//u-1 true //\uDB3D\uDC2A當(dāng)成兩個(gè)字符
console.log('u-2',/^\uDB3D/u.test('\uDB3D\uDC2A'));//u-2 false //\uDB3D\uDC2A當(dāng)成一個(gè)字符
console.log(/\u{61}/.test('a'));//false
console.log(/\u{61}/u.test('a'));//true
console.log(`\u{20BB7}`);//unicode編碼大于FFFF,即大于兩個(gè)字節(jié)
let s='??';
console.log(/^.$/.test(s));//false
console.log(/^.$/u.test(s));//true
console.log('test',/??{2}/.test('????'));//test false
console.log('test2',/??{2}/u.test('????'));//test2 true
//總結(jié),大于兩個(gè)字節(jié)長(zhǎng)度的字符,要加u
//但是仍然不能匹配換行符,回車(chē)符,行分隔符,段分隔符
//如果要能匹配,使用s修飾符,但是s修飾符es6尚未實(shí)現(xiàn)
}
四、字符串?dāng)U展
安裝補(bǔ)丁庫(kù),處理兼容:npm install babel-polyfill --save-dev
需要引入兼容庫(kù):
import 'babel-polyfill';
{
console.log('a','\u0061');//a a
console.log('a','\u20BB7');//a ?7 超過(guò)了0xFFF,即兩個(gè)字節(jié),會(huì)被當(dāng)成兩個(gè)字符
console.log('s',`\u{20BB7}`);//s ??
}
{
let s='??';
//es5
console.log('length',s.length);//2 (碼字大于兩個(gè)字節(jié),當(dāng)四個(gè)字節(jié)處理,計(jì)算長(zhǎng)度的時(shí)候每?jī)蓚€(gè)字節(jié)算一個(gè)長(zhǎng)度)
console.log('0',s.charAt(0));//0 亂碼
console.log('0',s.charAt(2));//0 亂碼
console.log('at0',s.charCodeAt(0));//at0 55362
console.log('at1',s.charCodeAt(1));//at0 57271
//es6
let s1='??a';
console.log('length',s1.length);//3
console.log('code0',s1.codePointAt(0));//134071 取出4個(gè)字節(jié)
console.log('code0',s1.codePointAt(0).toString(16));//20bb7
console.log('code1',s1.codePointAt(1));//57271 取出后兩個(gè)字節(jié)
console.log('code1',s1.codePointAt(2));//97 就是a
//.toString(16)轉(zhuǎn)成16進(jìn)制
}
{
//es5
console.log(String.fromCharCode('0x20BB7'));//亂碼
//es6
console.log(String.fromCodePoint('0x20BB7'));//??
}
{
let str='\u{20BB7}abc';
for (let i=0;i<str.length;i++){
console.log('es5',str[i]);//前兩個(gè)亂碼 a b c
}
for (let code of str){
console.log('es6',code);//?? a b c
}
}
{
let str='string';
console.log('includes',str.includes('r'));//true
console.log('start',str.startsWith('str'));//true
console.log('end',str.endsWith('ng'));//true
}
{
let str='abc';
//es5是用+
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
console.log('1'.padEnd(2,'0'));//10
}
//標(biāo)簽?zāi)0澹悍胖肵SS攻擊,處理多語(yǔ)言
{
let user={
name: 'list',
info: 'hello world'
};
console.log(abc`i am ${user.name},${user.info}`);
function abc(s,v1,v2) {
console.log(s, v1, v2);//["i am ", ",", "",] "list" "hello world"
return s+v1+v2;//i am ,,,listhello world
}
}
{
console.log(String.raw`Hi\n${1-2}`);//Hi \n-1
console.log('Hi\n${1+2}');//Hi 換行 ${1+2}
}
五、數(shù)值擴(kuò)展
{
console.log(0b11110111);//247 0b二進(jìn)制(大小寫(xiě)均可)
console.log(0o11111);//4681 0o八進(jìn)制(大小寫(xiě)均可)
}
{
console.log('15',Number.isFinite(15));//true
console.log('NaN',Number.isFinite(NaN));//false
console.log('1/0',Number.isFinite(1/0));//false
console.log('NaN',Number.isNaN(NaN));//true
console.log('0',Number.isNaN(0));//false
console.log('25',Number.isInteger(25));//true
console.log('25.0',Number.isInteger(25.0));//true 25.0=25
console.log('25.1',Number.isInteger(25.1));//false
console.log('25.0',Number.isInteger('25.0'));//false
console.log(Number.MAX_SAFE_INTEGER);
console.log(Number.MIN_SAFE_INTEGER);
console.log(Number.isSafeInteger(10));//true 是否位于上面兩個(gè)數(shù)的范圍內(nèi)
console.log(Number.isSafeInteger('a'));//false
//es5:Math.floor,Math.ceil
console.log(4.1,Math.trunc(4.1));//4
console.log(4.9,Math.trunc(4.9));//4
console.log('-5',Math.sign(-5));//-1
console.log('5',Math.sign(5));//1
console.log('0',Math.sign(0));//0
console.log('a',Math.sign('a'));//NaN
//開(kāi)立方根
console.log(Math.cbrt(-1));//-1
console.log(Math.cbrt(8));//2
}
六、數(shù)組擴(kuò)展
{
let arr=Array.of(3,4,7,9,11);
console.log('arr',arr);//[3,4,7,9,11]
console.log('arr',Array.of());//[]
}
{
let p=document.querySelectorAll('p');
let pArr=Array.from(p);//將上面的集合轉(zhuǎn)義成數(shù)組
pArr.forEach(function (item) {
console.log(item.textContent);
});
//map
console.log(Array.from([1,3,5],function (item) {return item+2;}));//3 5 7
//填充數(shù)組
console.log('fill-7',[1,'a',undefined].fill(7));//[7,7,7]
console.log('fill,pos',['a','b','c','d','e'].fill(7,1,3));//["a", 7, 7, "d", "e"] 1和3表示起始和截至位置,不包括位置3
for (let index of ['1','c','ks'].keys()){
console.log('keys',index);//0 1 2
}
for (let value of ['1','c','ks'].values()){
console.log('values',value);//1 c ks
}
for (let [index,value] of ['1','c','ks'].entries()){
console.log(index,value);
}
console.log([1,2,3,4,5].copyWithin(0,3,4));//[4,2,3,4,5] (從0開(kāi)始替換,從3開(kāi)始讀取,也就是第一個(gè)讀取的數(shù)是4,4是截至位置,也就是在位置4之前,因此只取4)
console.log([1,2,3,4,5,6].find(function (item) {
return item>3;//4,只找第一個(gè)
}));
console.log([1,2,3,4,5,6].findIndex(function (item) {
return item>3;//3
}));
console.log('number',[1,2,NaN].includes(1));//true
console.log('number',[1,2,NaN].includes(NaN));//true
}
使用擴(kuò)展運(yùn)算符(...)拷貝數(shù)組:const itemsCopy = [...items];
七、函數(shù)擴(kuò)展
{
function test(x, y='world') {
console.log('默認(rèn)值',x, y);
}
test();//undefined world
let x='test';
function test2(x,y=x) {
console.log('作用域',x,y)
}
test2('kill');//kill kill
}
{//rest參數(shù)
function test3(...arg) {//將輸入的參數(shù)都轉(zhuǎn)為數(shù)組
for (let v of arg){
console.log('rest',v);//a b c
}
}
test3('a','b','c');
//將數(shù)組轉(zhuǎn)成離散的值
console.log(...[1,2,4]);//1 2 4
console.log('a',...[1,2,4]);//a 1 2 4
}
{//箭頭函數(shù)
let arrow = v => v+2;//v是參數(shù),v+2是返回值
console.log('arrow',arrow(3));//5
//無(wú)參數(shù)情況下
let arrow2 = ()=> 2;
}
{//偽調(diào)用:函數(shù)的最后一句話是不是函數(shù)
function tail(x) {
console.log('tail',x);
}
function fx(x) {
return tail(x);
}
fx(123);//tail 123
}
八、對(duì)象擴(kuò)展
這里的對(duì)象指Object對(duì)象
{
// 簡(jiǎn)潔表達(dá)法
let o=1;
let k=2;
let es5={
o:o,
k:k
};
let es6={
o,
k
};
console.log(es5,es6);//結(jié)果是一樣的
let es5_mrthod={
hello:function () {
console.log('hello');
}
};
let es6_method={
hello(){
console.log('hello');
}
};
console.log(es5_mrthod,es6_method);//結(jié)果是一樣的
//屬性表達(dá)式
let a='b';
let es5_obj={
a: 'c'
};
let es6_obj={
[a]:'c' //這里的a是變量,即b
};
console.log(es5_obj,es6_obj);
//新增API
console.log('字符串',Object.is('abc','abc'));//true 相當(dāng)于===
console.log('數(shù)組',Object.is([],[]),[]===[]);//false false 引用地址不同
//淺復(fù)制(只改引用地址)
console.log('拷貝',Object.assign({a:'a'},{b:'b'}));//{a: "a", b:"b"}
let test={k:123,o:456};
for (let [key,value] of Object.entries(test)){
console.log(key,value);
}
}
不要聲明之后又給對(duì)象添加新屬性,如果一定非要加請(qǐng)使用Object.assign。
九、Symbol用法
Symbol的概念:用symbol聲明的變量,永遠(yuǎn)不相等。
{
//聲明1
let a1=Symbol();
let a2=Symbol();
console.log(a1===a2);//false
//聲明2
let a3=Symbol.for('a3');//'a3'會(huì)先檢查a3是否在全局注冊(cè)過(guò),如果是,返回該值
let a4=Symbol.for('a3');
console.log(a3===a4);//true
//使用場(chǎng)景
let a5=Symbol.for('abc');
let obj={
[a5]: '123',
'abc': 345,
'c': 456
};
console.log(a5,obj);//Symbol(abc) {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(item,obj[item]);//可以將所有的key-value值打印出來(lái)
});
}
十、set-map數(shù)據(jù)結(jié)構(gòu)
數(shù)據(jù)結(jié)構(gòu):set、weakset、map、weakmap
Object的key必須是字符串或者Symbol數(shù)據(jù)類型,而map的key可以是任意數(shù)據(jù)類型。
weakset與set支持的數(shù)據(jù)類型不同,weakset的元素只能是數(shù)據(jù)對(duì)象,且weakset中的對(duì)象是弱引用(地址引用),即不會(huì)檢測(cè)這個(gè)對(duì)象是否在其他地方用過(guò),也就意味著不會(huì)和垃圾回收機(jī)制掛鉤(不會(huì)檢測(cè)是否被回收)。
{//set
let list=new Set();//沒(méi)有重復(fù)值
list.add(5);
list.add(7);
console.log('size',list.size);//2
let arr=[1,2,3,4,5];
let list1=new Set(arr);
console.log('size',list1.size);//5
let list2=new Set();
list2.add(1);
list2.add(2);
list2.add(1);
console.log('size',list2.size);//2
//重要應(yīng)用場(chǎng)景:去重
let arr1=[1,2,3,1,2];
let list3=new Set(arr1);
console.log('unique',list3);//{1,2,3}
let arr2=[1,2,3,1,"2"];
let list4=new Set(arr2);
console.log('unique',list4);//{1,2,3,"2"}
let arr3=['add','delete','clear','has'];
let list5=new Set(arr3);
console.log(list5.has('add'));//true
console.log('delete',list5.delete('add'),list5);//true {"delete","clear","has"}
list5.clear();
console.log(list5);//set(0)
//key和value都是一樣的
let list6=new Set(arr3);
for (let key of list6.keys()){
console.log('keys',key);
}
for (let value of list6.values()){
console.log('values',value)
}
for (let value of list6.values()){
console.log('values',value)
}
for (let [key,value] of list6.entries()){
console.log(key,value)
}
list6.forEach(function (item) {
console.log(item);
});
}
{//weakset
let weakList=new WeakSet();
let arg={};
weakList.add(arg);
//weakList.add(2);//報(bào)錯(cuò)
console.log(weakList);
//無(wú)clear方法,無(wú)size屬性,不能遍歷
}
{//map
let map=new Map();
let arr=['123'];
map.set(arr,459);
console.log(map,map.get(arr));
//第二種定義方式
let map1=new Map([['a',123],['b',456]]);
console.log(map1);//{"a"=>123,"b"=>456
console.log('size',map1.size);
console.log('delete',map.delete('a'),map);
console.log('clear',map.clear(),map);
//遍歷同set
}
{//weakmap
let weakMap=new WeakMap();//接收對(duì)象必須是對(duì)象
//無(wú)size對(duì)象,無(wú)clear方法,不能遍歷
}
十一、map-set與數(shù)組和對(duì)象的比較
{
//map與數(shù)組的對(duì)比
let map=new Map();
let array=[];
//增
map.set('a',123);
array.push({a:123});
console.info('map-array',map, array);
//查
let map_exists=map.has('a');//true
let array_exists=array.find(item =>item.a);//{a:123}
//改
map.set('a',2);
array.forEach(item => item.a?item.a=2:'');
//刪
map.delete('a');
let index=array.findIndex(item=>item.a);
array.splice(index,1);
}
{
//set和array的對(duì)比
let set=new Set();
let array=[];
//增
set.add({t:1});
//查
let set_exist=set.has({t:1});
//改
set.forEach(item=>item.t?item.t=2:'');
//刪
set.forEach(item=>item.t?set.delete(item):'');
}
{
//map、set與object的區(qū)別
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_exists: map.has('t'),
set_exists: set.has(item),
obj_exists: 't' in obj
});
//改
map.set('t',2);
item.t = 2;//set的改,引用類型
obj['t']=2;
//刪
map.delete('t');
set.delete(item);
delete obj['t'];
}
如果只是簡(jiǎn)單的key: value結(jié)構(gòu),建議優(yōu)先使用Map,因?yàn)镸ap提供方便的遍歷機(jī)制。
十二、Proxy和Reflect
{
//proxy:代理
let obj={ //原始對(duì)象,存儲(chǔ)真實(shí)數(shù)據(jù)
time: '2017-08-04',
name: 'net',
_r: 123
};
let monitor=new Proxy(obj,{//通過(guò)Proxy新生成一個(gè)對(duì)象
//攔截對(duì)象屬性的讀取
get(target,key){
return target[key].replace('2017','2018');
},
//攔截對(duì)象屬性的設(shè)置
set(target,key,value){
if (key === 'name') {
return target[key]=value;
}else{
return target;//不做任何操作
}
},
//攔截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.getOwnPropertNames
ownKeys(target){
return Object.keys(target).filter(item=>item!='time');
}
});
//用戶使用的是monitor
console.log(monitor.time);
monitor.time='2018';
console.log(monitor.time);//沒(méi)有變化
monitor.name = 'com';
console.log(monitor.name);//com
console.log('name' in monitor);//true
delete monitor['time'];
console.log(monitor);//未刪除
delete monitor._r;
console.log(monitor);//刪除
console.log(Object.keys(monitor));//"name"
}
{
//reflect:方法同proxy
let obj={ //原始對(duì)象,存儲(chǔ)真實(shí)數(shù)據(jù)
time: '2017-08-04',
name: 'net',
_r: 123
};
console.log(Reflect.get(obj,'time'));//2017-08-04
Reflect.set(obj,'name','com');
console.log(obj);//com
console.log(Reflect.has(obj,'name'));//true
}
{
//使用場(chǎng)景:數(shù)據(jù)類型的校驗(yàn)(與業(yè)務(wù)解耦的校驗(yàn)?zāi)K)
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]){
return Reflect.set(target,key, value,proxy);
}else{
throw Error(`不能設(shè)置${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;//error:不能設(shè)置name為48
}
十三、類和對(duì)象
{
//類的基本定義和生成實(shí)例
class Parent{
//es6中定義構(gòu)造函數(shù)
constructor(name='com'){
this.name=name;
}
}
let v_parent=new Parent('net');
console.info(v_parent);
//繼承
class Child extends Parent{
}
console.log(new Child());//{name:"com"}
//繼承傳遞參數(shù),將參數(shù)傳遞給父類
class Child2 extends Parent{
constructor(name='child'){
super(name);//super一定放在構(gòu)造函數(shù)的第一行
this.type='child';
}
}
console.log(new Child2());//{name:"child",type:"child"}
//getter,setter
class Parent2{
constructor(name='com'){
this.name=name;
}
get longName(){
return 'long'+this.name;
}
set longName(value){
this.name=value;
}
}
let v_parent2=new Parent2();
v_parent2.longName='net';
console.log(v_parent2.longName);//longnet
//靜態(tài)方法、靜態(tài)屬性
class Parent3{
constructor(name='com'){
this.name=name;
}
static tell(){//靜態(tài)方法
console.log('tell');
}
}
Parent.type = 'test';//這個(gè)就是靜態(tài)屬性
Parent3.tell();
}
十四、Promise
Promise是異步編程的一種解決方案。
{
//使用回調(diào)的方式
//缺點(diǎn):如果是按順序執(zhí)行a,b,c...,代碼的寫(xiě)法會(huì)非常復(fù)雜,代碼的復(fù)雜影響后期的維護(hù)
let ajax=function (callback) {
console.log('執(zhí)行');
setTimeout(function () {
callback&&callback.call();
},1000);
};
ajax(function () {
console.log('timeout1');
});
//使用promise解決方案
let ajax1=function () {
console.log('執(zhí)行1');
return new Promise(function (resolve,reject) {
//resolve:要執(zhí)行下一步的操作
//reject:要中斷當(dāng)前的操作
setTimeout(function () {
resolve();
},1000);
});
};
ajax1().then(function () {
console.log('promise','timeout2');
return new Promise(function (resolve,reject) {
setTimeout(function () {
resolve();
},1000);
});
})
.then(function () {
console.log('promise','timeout3');
});
}
{//捕獲錯(cuò)誤
let ajax=function (num) {
console.log('執(zhí)行2');
return new Promise(function (resolve,reject) {
if (num>5){
resolve();
}else {
throw new Error('出錯(cuò)了');
}
});
};
ajax(2).then(function () {
console.log(6);
}).catch(function (err) {
console.log(err);
});
}
{//應(yīng)用場(chǎng)景
//所有圖片加載完再加載頁(yè)面
function loadImg(src) {
return new Promise((resolve, reject)=>{
let img=document.createElement('img');
img.src=src;
img.onload=function () {//圖片加載完成
resolve(img);
};
img.onerror = function () {
reject(err);
};
});
}
function showImgs(imgs) {
imgs.forEach(function (img) {
document.body.appendChild(img);
});
}
Promise.all([
loadImg('http://i4.buimg.com/567571/df1ef0720bea6832.png'),
loadImg('http://i4.buimg.com/567571/2b07ee25b08930ba.png'),
loadImg('http://i4.buimg.com/567571/2b07ee25b08930ba.png')
]).then(showImgs);
}
{//應(yīng)用場(chǎng)景
//有一個(gè)圖片加載完就添加到頁(yè)面
function loadImg(src) {
return new Promise((resolve, reject)=>{
let img=document.createElement('img');
img.src=src;
img.onload=function () {//圖片加載完成
resolve(img);
};
img.onerror = function () {
reject(err);
};
});
}
function showImgs(img) {
let p=document.createElement('p');
p.appendChild(img);
document.body.appendChild(p);
}
Promise.race([
loadImg('http://i4.buimg.com/567571/df1ef0720bea6832.png'),
loadImg('http://i4.buimg.com/567571/2b07ee25b08930ba.png'),
loadImg('http://i4.buimg.com/567571/2b07ee25b08930ba.png')
]).then(showImgs);
}
十五、Iterator和for...of循環(huán)
{
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:false}
}
{
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(){//寫(xiě)遍歷過(guò)程
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
}
}
{//for...of
let arr=['hello','world'];
for (let value of arr){
console.log(value);//hello world
}
}
十六、Genertor
Genertor也是異步編程的一種解決方案,但是相對(duì)promise更高級(jí)一點(diǎn)。
{
let state=function* (){
while(1){
yield 'A';
yield 'B';
yield 'C';
}
};
let status=state();
console.log(status.next());//A done:false
console.log(status.next());//B done:false
console.log(status.next());//C done:false
console.log(status.next());//A done:false
console.log(status.next());//B done:false
}
{//應(yīng)用場(chǎng)景:抽獎(jiǎng)
let draw=function (count) {
//具體抽獎(jiǎng)邏輯略
console.info(`剩余${count}次`);
};
let residue=function* (count) {
while(count>0){
count--;
yield draw(count);
}
};
let start=residue(5);
let btn=document.createElement('button');
btn.id='start';
btn.textContent='抽獎(jiǎng)';
document.body.appendChild(btn);
document.getElementById('start').addEventListener('click',function () {
start.next();
},false);
}
{//應(yīng)用場(chǎng)景:定期向服務(wù)端獲取數(shù)據(jù),使用長(zhǎng)輪詢
let ajax=function* () {
yield new Promise(function (resolve,reject) {
setTimeout(function () {
resolve({code:0})
},200);
})
};
let pull=function () {
let generator=new ajax();
let step=generator.next();
step.value.then(function (d) {//step.value就是promise實(shí)例
if (d.code!=0) {//表示數(shù)據(jù)未更新
setTimeout(function () {
console.log('wait');
pull();
},1000);
}else{
console.log(d);
}
});
};
pull();
}
十七、Decorators
修飾器:一個(gè)函數(shù),用來(lái)修改類的行為。
需要安裝插件:npm install babel-plugin-transform-decorators-legacy --save-dev
.babelrc:"plugins":["transform-decorators-legacy"]
{
let readonly=function (target,name,descriptor) {
//target:修改類本身
//name:修改屬性名稱
//descriptor:屬性的描述對(duì)象
descriptor.writable=false;
return descriptor;
};
class Test{
@readonly //修飾器
time(){
return '2017-03-11';
}
}
let test=new Test();
console.log(test.time());//2017-03-11
// test.time=function(){
// console.log('reset');//error: Cannot assign to read only property 'time' of object
// };
//在類外面操作必須在class前
let typename=function (target,name,descriptor) {
target.myname='hello';//靜態(tài)屬性
};
@typename
class Test2{
}
console.log(Test2.myname);//hello
//第三方庫(kù)修飾器的js庫(kù):core-decorators(npm install core-decorators)
}
{//應(yīng)用場(chǎng)景:埋點(diǎn)
//將埋點(diǎn)系統(tǒng)從業(yè)務(wù)邏輯中拆離
let log=(type)=>{
return function (target,name,descriptor) {
let src_method=descriptor.value;
descriptor.value=(...arg)=>{
src_method.apply(target,arg);
console.info(`log ${type}`);
}
}
};
class AD{
@log('show')
show(){
console.log('ad is show');
}
@log('type')
click(){
console.log('ad is click');
}
}
let ad=new AD();
ad.show();//ad is show log show
ad.click();//ad is click log type
}
十八、模塊化
ES6的模塊化語(yǔ)法:引入import、導(dǎo)出export
導(dǎo)出:
export let A=123;
export function test() {
console.log('test');
}
export class Hello {
test(){
console.log('class');
}
}
導(dǎo)入:
import {A,test,Hello} from "./class/lesson17";
console.log(A, test, Hello);
可以只導(dǎo)入部分變量:
import {A} from "./class/lesson17";
console.log(A);
起別名:
import * as lesson from "./class/lesson17";
console.log(lesson.A);
不給導(dǎo)出數(shù)據(jù)起名字(推薦):
let A=123;
function test() {
console.log('test');
}
class Hello {
test(){
console.log('class');
}
}
export default {
A,
test,
Hello
}
導(dǎo)入:
import lesson from "./class/lesson17";
console.log(lesson.A);