一燃领、解構(gòu)賦值
- 數(shù)組的解構(gòu)賦值
{
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, c;
[a, b, c=3] = [1, 2]
console.log(a,b,c) // 1,2,3
}
// 應(yī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()
console.log(a,b) // 1,2
}
{
function f(){
return [1,2,3,4,5]
}
let a,b,c;
[a,,,b] = f()
console.log(a,b) // 1,4
}
{
function f(){
return [1,2,3,4,5]
}
let a,b,c;
[a,,...b] = f()
console.log(a,b) // 1,[3,4,5]
}
二、 對(duì)象解構(gòu)賦值
{
let a,b;
({a,b} = {a:1,b:2})
console.log(a,b) // 1,2
}
{
let o = {p:42,q:true}
let {p,q} = o;
console.log(p,q) // 42 true
}
{
let {a=5,b=10} = {a:3}
console.log(a,b) // 3 10
}
// 應(yīng)用場景
{
let metaData = {
title: 'abc',
test:[{
title: 'test',
desc: 'description'
}]
}
let {title:esTitle,test:[{title:cnTitle}]} = metaData
console.log(esTitle,cnTitle) // abc test
}
// 對(duì)象內(nèi)寫函數(shù)時(shí)不需要再加function,而且對(duì)象內(nèi)支持變量
const k = "arr";
const s = "s"
const result = {
[k+1]: 1,
s,
q(){
console.log("??")
}
}
result.q()
console.log(result.arr1)
console.log(c.startsWith("we")) // 以什么開始
console.log(c.endsWith("!")) // 以什么結(jié)束
console.log(c.includes("family")) // 包含什么
const c = test `${a} $ family!`
function test(strs,...values) {
console.log(strs,values)
}
// NaN與NaN不相等毁枯,如果想要想等需要采用以下方法
console.log(NaN === NaN);
console.log(Object.is(NaN, NaN));
三种玛、正則新特性
{
let regex = new RegExp('xyz','i'); // i表示忽略大小寫
let regex2 = new RegExp(/xyz/i);
console.log(regex.test('xyz123'),regex2.test('xyz123')); // true true
let regex3 = new RegExp(/xyz/ig,'i'); // es6中后面的修飾符會(huì)覆蓋掉前面的修飾符
console.log(regex3.flags); // i
}
// y修飾符
{
let s = 'bbb_bb_b';
let a1 = /b+/g;
let a2 = /b+/y;
console.log('one',a1.exec(s),a2.exec(s)); // one ["bbb", index: 0, input: "bbb_bb_b"] ["bbb", index: 0, input: "bbb_bb_b"]
console.log('two',a1.exec(s),a2.exec(s)); // two ["bb", index: 4, input: "bbb_bb_b"] null
// g修飾符是找到就可以,y修飾符必須從上一次匹配的位置開始
console.log(a1.sticky,a2.sticky); // 判斷正則對(duì)象是否開啟了y修飾符 false true
}
// u修飾符
{
console.log('u-1',/^\uD83D/.test('\uD83D\uDC2A')); // \uD83D\uDC2A當(dāng)作兩個(gè)字符
console.log('u-2',/^\uD83D/u.test('\uD83D\uDC2A')); // \uD83D\uDC2A當(dāng)作一個(gè)字符
console.log(/\u{61}/.test('a')); // false
console.log(/\u{61}/u.test('a')); // true
console.log(/\u{20BB7}/u.test('??')); // true
// 點(diǎn)(.)字符不能識(shí)別碼點(diǎn)大于0xFFFF的Unicode字符祭示,必須加上u修飾符稠歉。
let s = '??';
console.log('大于0xFFFF的Unicode字符',/^.$/.test(s)); // false
console.log('使用u字符',/^.$/u.test(s)); // true
// 使用u修飾符后怒炸,所有量詞都會(huì)正確識(shí)別大于碼點(diǎn)大于0xFFFF的Unicode字符纠炮。
console.log('量詞',/a{2}/.test('aa')); // true
console.log('量詞',/a{2}/u.test('aa')); // true
console.log('量詞',/??{2}/.test('????')); // false
console.log('量詞',/??{2}/u.test('????')); // true
}
{
// #正則表達(dá)式中恢口,點(diǎn)(.)是一個(gè)特殊字符因妇,代表任意的單個(gè)字符婚被,但是行終止符(line terminator character)除外
// U+000A 換行符(\n)
// U+000D 回車符(\r)
// U+2028 行分隔符(line separator)
// U+2029 段分隔符(paragraph separator)
// 只是一個(gè)提案目前還不支持
// let reg=/test.go/s;
// console.log(reg.test('test\ngo'));
// console.log(reg.test('test\ngo'));
console.log('s變通方法',/foo.bar/.test('foo\nbar'));
console.log('s變通方法',/foo[^]bar/.test('foo\nbar'));
}
四址芯、字符串?dāng)U展
// 字符串?dāng)U展
// 處理unicode編碼處理大于0xFFFF
{
console.log('a', '\u0061'); // a a
console.log('s', '\u20BB7'); // s ?7 \u20BB7太長谷炸,被當(dāng)成了\u20BB和7兩個(gè)字符
console.log('s', '\u{20BB7}'); // s ?? es6方法旬陡,將字符集用{}包起來
}
{
let s = '??';
console.log('length',s.length) // 2 碼值大于兩個(gè)字節(jié),所以當(dāng)作4個(gè)字節(jié)處理,兩個(gè)字節(jié)為1個(gè)長度
console.log('0',s.charAt(0)); // 0 ? 取第一個(gè)位置的字符
console.log('1',s.charAt(1)); // 1 ?
console.log('at0',s.charCodeAt(0)); // at0 55362 // 取第一個(gè)位置的碼值
console.log('at1',s.charCodeAt(1)); // at1 57271
// es6 取碼值
let s1 = '??a';
console.log('length',s1.length) // 3
console.log('code0',s1.codePointAt(0)); // code0 134071
console.log('code0',s1.codePointAt(0).toString(16)); // code0 20bb7
console.log('code1',s1.codePointAt(1)); // code1 57271
console.log('code2',s1.codePointAt(2)); // code2 97
}
// 轉(zhuǎn)換為字符
{
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){
console.log('es6',code); // es6 ?? es6 a es6 b es6 c
}
}
// 字符串中是否包含某些字符
{
let str="string";
console.log('includes',str.includes("c")); // false
console.log('start',str.startsWith('str')); // true
console.log('end',str.endsWith('ng')); // true
}
// 重復(fù)
{
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
}
// es7草案
{
console.log('1'.padStart(2,'0')); // 01 第一個(gè)參數(shù)是長度,第二個(gè)是補(bǔ)什么 比如日期小于10月補(bǔ)0
console.log('1'.padEnd(2,'0')); // 10
}
// 標(biāo)簽?zāi)0?{
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); // ["i am ", ",", "", raw: Array(3)] "list" "hello world"
return s+v1+v2
}
}
// String.raw對(duì)所有字符串進(jìn)行轉(zhuǎn)譯
{
console.log(String.raw`Hi\n${1+2}`); // Hi\n3
console.log(`Hi\n${1+2}`); // Hi 3
}
五菜职、數(shù)值擴(kuò)展
// es6中二進(jìn)制以0B開頭酬核,八進(jìn)制以0o開頭举瑰,大小寫都可以
{
console.log('B',0B111110111);
console.log(0o767);
}
{
// 是否有盡之內(nèi)
console.log('15',Number.isFinite(15)); // true
console.log('NaN',Number.isFinite(NaN)); // false
console.log('1/0',Number.isFinite('true'/0)); // false
// 是不是數(shù)
console.log('NaN',Number.isNaN(NaN)); // true
console.log('0',Number.isNaN(0)); // false
}
{
// 判斷是否是整數(shù)
console.log('25',Number.isInteger(25)); // true
console.log('25.0',Number.isInteger(25.0)); // true
console.log('25.1',Number.isInteger(25.1)); // false
console.log('25',Number.isInteger('25')); // false
}
// 判斷一個(gè)數(shù)是否在-2^53與2^53之間,超過這個(gè)范圍數(shù)就不準(zhǔn)了
{
console.log(Number.MAX_SAFE_INTEGER,Number.MIN_SAFE_INTEGER); // 9007199254740991 -9007199254740991
console.log('10',Number.isSafeInteger(10)); // 10 true
console.log('a',Number.isSafeInteger('a')); // a false
}
// 返回一個(gè)小數(shù)的整數(shù)部分
{
console.log(4.1,Math.trunc(4.1)); // 4
console.log(4.9,Math.trunc(4.9)); // 4
}
// 判斷正負(fù)
{
console.log('-5',Math.sign(-5)); // -1
console.log('0',Math.sign(0)); // 0
console.log('5',Math.sign(5)); // 1
console.log('50',Math.sign('50')); // 1
console.log('foo',Math.sign('foo')); // NaN
}
// 立方根計(jì)算
{
console.log('-1',Math.cbrt(-1)); // -1
console.log('8',Math.cbrt(8)); // 2
}
// 三角函數(shù),對(duì)數(shù),查api
六忍些、數(shù)組擴(kuò)展
// of把一組數(shù)據(jù)變量轉(zhuǎn)化為數(shù)據(jù)類型
{
let arr = Array.of(3,4,7,9,11);
console.log('arr=',arr); // [3, 4, 7, 9, 11]
let empty=Array.of();
console.log('empty',empty); // []
}
// Array.from把類數(shù)組轉(zhuǎn)化為數(shù)組
{
let p=document.querySelectorAll('p');
let pArr=Array.from(p);
pArr.forEach(function(item){
console.log(item.textContent); // hello es6 world
});
console.log(Array.from([1,3,5],function(item){return item*2})); // [2, 6, 10]
}
// fill替換
{
console.log('fill-7',[1,'a',undefined].fill(7)); // [7, 7, 7]
console.log('fill,pos',['a','b','c'].fill(7,1,3)); // ["a", 7, 7] 從位置1開始替換到位置3
}
{
for(let index of ['1','c','ks'].keys()){ // keys() 返回?cái)?shù)組下標(biāo)的集合
console.log('keys',index); // 0 1 2
}
for(let value of ['1','c','ks'].values()){ // values() 返回?cái)?shù)組值
console.log('values',value); // 1,c,ks
}
for(let [index,value] of ['1','c','ks'].entries()){ // entries() 值和鍵
console.log('values',index,value); // 0 1 1 c 2 ks
}
for(let value of ['1','c','ks']){
console.log('values',value); // 1 c ks
}
}
// 當(dāng)前數(shù)組內(nèi)部改變位置
{
console.log([1,2,3,4,5].copyWithin(0,3,4)); // [4, 2, 3, 4, 5]
}
// 查找
{
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})); // 返回第一個(gè)下標(biāo)
}
// 數(shù)組中是否包括某個(gè)值
{
console.log('number',[1,2,NaN].includes(1)); // true
console.log('number',[1,2,NaN].includes(NaN)); // true
}
七搅窿、函數(shù)擴(kuò)展
- 箭頭函數(shù)沒有arguments(建議使用更好的語法男应,剩余運(yùn)算符替代)
- 箭頭函數(shù)沒有prototype屬性游桩,沒有constructor薪铜,即不能用作與構(gòu)造函數(shù)(不能用new關(guān)鍵字調(diào)用)
- 箭頭函數(shù)沒有自己this谓娃,它的this是詞法的滨达,引用的是上下文的this,即在你寫這行代碼的時(shí)候就箭頭函數(shù)的this就已經(jīng)和外層執(zhí)行上下文的this綁定了(這里個(gè)人認(rèn)為并不代表完全是靜態(tài)的,因?yàn)橥鈱拥纳舷挛娜允莿?dòng)態(tài)的可以使用call,apply,bind修改,這里只是說明了箭頭函數(shù)的this始終等于它上層上下文中的this)
// 參數(shù)默認(rèn)值
{
function test(x, y = 'world'){ // 有默認(rèn)值的參數(shù)后面不可以再聲明沒有默認(rèn)值的參數(shù) x, y = 'world', c是錯(cuò)誤的
console.log('默認(rèn)值',x,y);
}
test('hello'); // hello world
test('hello','kill'); // hello kill
}
{
let x='test';
function test2(x,y=x){
console.log('作用域',x,y);
}
test2('kill'); // kill kill
}
{
function test3(...arg){
for(let v of arg){
console.log('rest',v); // rest 1 rest 2 rest 3 rest 4 rest a
}
}
test3(1,2,3,4,'a');
}
// 展開運(yù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;
let arrow2 = () => 5;
console.log('arrow',arrow(3)); // 6
console.log(arrow2()); // 5
}
// 偽調(diào)用,提升性能
{
function tail(x){
console.log('tail',x); // tail 123
}
function fx(x){
return tail(x)
}
fx(123)
}
八、對(duì)象擴(kuò)展
{
// 簡潔表示法
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}
// 以下兩種寫法是等價(jià)的
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
}
{
// 屬性表達(dá)式
let a='b';
let es5_obj={
b:'c'
};
let es6_obj={
[a]:'c'
}
console.log(es5_obj,es6_obj); // {b: "c"} {b: "c"}
}
{
// 新增API
console.log('字符串',Object.is('abc','abc'),'abc'==='abc'); // 字符串 true true
console.log('數(shù)組',Object.is([],[]),[]===[]); // 數(shù)組 false false
// 注意這個(gè)是淺拷貝,淺拷貝只拷貝引用地址
console.log('拷貝',Object.assign({a:'a'},{b:'b'})); // 拷貝 {a: "a", b: "b"},第一個(gè)是要拷貝到的對(duì)象谓传,第二個(gè)是拷貝的內(nèi)容
let test={k:123,o:456};
for(let [key,value] of Object.entries(test)){
console.log([key,value]); // ["k", 123] ["o", 456]
}
}
{
// 擴(kuò)展運(yùn)算符 babel支持不好蜈项,會(huì)報(bào)錯(cuò),實(shí)踐中暫時(shí)沒法用
// let {a,b,...c}={a:'test',b:'kill',c:'ddd',d:'ccc'};
// console.log(c) // c={c:'ddd',d:'ccc'}
}
九续挟、Symbol
{
// 聲明
let a1 = Symbol();
let a2 = Symbol();
console.log(a1===a2); // false
// for會(huì)查找全局中是否有a3,如果有紧卒,取a3的值,如果沒有诗祸,會(huì)執(zhí)行Symbol()
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': '234',
'c': '456'
};
console.log('obj',obj); // obj {abc: "234", c: "456", Symbol(abc): "123"}
// 遍歷的時(shí)候是拿不到Symbol(abc)值的
for(let [key,value] of Object.entries(obj)){
console.log('let of',key,value); // let of abc 234 let of c 456
}
// 拿到Symbol(abc)值
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 234 ownkeys c 456 ownkeys Symbol(abc) 123
})
}
十跑芳、數(shù)據(jù)結(jié)構(gòu)(set, map)
// set中的內(nèi)容不可重復(fù)
{
let list = new Set();
list.add(5);
list.add(7);
// 數(shù)組長度size
console.log('size',list.size); // 2
}
{
let arr = [1,2,3,4,5];
let list = new Set(arr);
console.log('size',list.size); // 5
}
{
let list = new Set();
list.add(1);
list.add(2);
list.add(1);
console.log('list',list); // {1, 2}
let arr=[1,2,3,1,'2'];
let list2=new Set(arr);
console.log('unique',list2); // {1, 2, 3, "2"}
}
{
let arr=['add','delete','clear','has'];
let list=new Set(arr);
console.log('has',list.has('add')); // has true
list.delete('add');
console.log('delete',list); // delete {"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
}
// 默認(rèn)就是values
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
}
// weakSet和set支持的數(shù)據(jù)類型不同,只能是對(duì)象脖含,并且是弱引用关拒,只拷貝引用地址,他沒有size等屬性归露,且不能遍歷
{
let weakList=new WeakSet();
let arg={};
weakList.add(arg);
// weakList.add(2); // Invalid value used in weak set
console.log('weakList',weakList); // weakList WeakSet {{…}}
}
// map對(duì)object的補(bǔ)充陕贮,key可以事任何東西攀圈,object的key是字符串
{
let map = new Map();
let arr=['123'];
// 用數(shù)組arr作key,添加用set
map.set(arr,456); // map Map(1) {Array(1) => 456} 456
// 獲取arr的值用get
console.log('map',map,map.get(arr));
}
{
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
map.delete('a');
console.log('delete',map); // delete Map(1) {"b" => 456}
console.log('clear',map.clear(),map); // clear undefined Map(0) {}
}
// 與Set和weakSet區(qū)別相同
{
let weakmap=new WeakMap();
let o={};
weakmap.set(o,123);
console.log(weakmap.get(o)); // 123
}
// 數(shù)據(jù)結(jié)構(gòu)橫向?qū)Ρ群眩雎茜瑁檎龆南辔叮瑒h
// map與array對(duì)比
{
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的對(duì)比
{
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) {{…}} [{…}]
// 刪
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對(duì)比
{
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); // map-set-obj {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('map-set-obj-modify',obj,map,set); // map-set-obj-modify {t: 2} Map(1) {"t" => 2} Set(1) {{…}}
// 刪除
map.delete('t');
set.delete(item);
delete obj['t'];
console.info('map-set-obj-empty',obj,map,set); // map-set-obj-empty {} Map(0) {} Set(0) {}
}
十一凛辣、Proxy與Reflect 代理,反射
// Proxy 保護(hù)一些對(duì)象
{
let obj={ // 原始對(duì)象
time:'2017-03-11',
name:'net',
_r:123
};
// 攔截代理商
let monitor=new Proxy(obj,{
// 讀
get(target,key){
return target[key].replace('2017','2018'); // 把有2017的替換成2018
},
// 設(shè)置,例如只能修改name,其他不能修改
set(target,key,value){ // 第一個(gè)參數(shù)指obj對(duì)象浦夷,第二個(gè)指key罐孝,第三個(gè)是key值
if(key==='name'){
return target[key]=value;
}else{
return target[key];
}
},
// 攔截key in object操作, 判斷是否擁有某個(gè)屬性
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){ // 不能遍歷key為time的屬性
return Object.keys(target).filter(item=>item!='time')
}
});
console.log('get',monitor.time); // get 2018-03-11
monitor.time='2016';
monitor.name='mukewang';
console.log('set',monitor.time,monitor); // set 2018-03-11 Proxy {time: "2017-03-11", name: "mukewang", _r: 123}
console.log('has','name' in monitor,'time' in monitor); // has true false
console.log('ownKeys',Object.keys(monitor)); // ownKeys (2) ["name", "_r"]
delete monitor.time;
console.log('delete',monitor); // delete Proxy {time: "2017-03-11", name: "mukewang", _r: 123}
delete monitor._r;
console.log('delete',monitor); // delete Proxy {time: "2017-03-11", name: "mukewang"}
console.log('obj',obj); // obj {time: "2017-03-11", name: "mukewang"}
}
// Reflect 用object的可以用Reflect
{
let obj={
time:'2017-03-11',
name:'net',
_r:123
};
console.log('Reflect get',Reflect.get(obj,'time')); // Reflect get 2017-03-11
Reflect.set(obj,'name','mukewang');
console.log(obj); // {time: "2017-03-11", name: "mukewang", _r: 123}
console.log('has',Reflect.has(obj,'name')); // has true
}
// 實(shí)際應(yīng)用
{
function validator(target,validator){ // 校驗(yàn)?zāi)K
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) // 返回到真實(shí)對(duì)象上
}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
},
mobile(val){
}
}
class Person{
constructor(name,age){
this.name=name;
this.age=age;
this.mobile='1111';
return validator(this,personValidators)
}
}
const person=new Person('lilei',30);
console.info(person); // Proxy {name: "lilei", age: 30, mobile: "1111"}
// person.name = 48; // 不能設(shè)置name到48
person.name='Han mei mei';
console.info(person); // Proxy {name: "lilei", age: 30, mobile: "1111"}
}
十二、 類與對(duì)象
class MathHandle {
//
}
console.log(typeof MathHandle) // "function"
console.log(MathHandle === MathHandle. prototype. constructor) // true
//這種語法糖形式,看起來和實(shí)際原理不一樣的東西赊豌,我個(gè)人不太贊同
//形式上強(qiáng)行模仿java C#花沉,卻失去了它的本性和個(gè)性
// 基本定義和生成實(shí)例
{
class Parent{
constructor(name='mukewang'){ // 構(gòu)造函數(shù)
this.name=name;
}
}
let v_parent=new Parent('v');
console.log('構(gòu)造函數(shù)和實(shí)例',v_parent); // 構(gòu)造函數(shù)和實(shí)例 Parent {name: "v"}
}
// // 繼承
{
class Parent{
constructor(name='mukewang'){
this.name=name;
}
}
class Child extends Parent{
}
console.log('繼承',new Child()); // 繼承 Child {name: "mukewang"}
}
// 繼承傳遞參數(shù)
{
class Parent{
constructor(name='mukewang'){
this.name=name;
}
}
class Child extends Parent{
constructor(name='child'){
super(name); // 如果super()為空俩功,將默認(rèn)使用父類所有參數(shù)值
this.type='child'; // 自定義的一定要放在super()后面,即super()在第一行
}
}
console.log('繼承傳遞參數(shù)',new Child('hello')); // 繼承傳遞參數(shù) _Child {name: "hello", type: "child"}
}
// getter,setter
{
class Parent{
constructor(name='mukewang'){
this.name=name;
}
get longName(){ // 這是屬性碰声,不是函數(shù)诡蜓,下面set同樣
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
}
// 靜態(tài)方法,靜態(tài)方法通過類取調(diào)用而不是通過實(shí)例去調(diào)用
{
class Parent{
constructor(name='mukewang'){
this.name=name;
}
static tell(){
console.log('tell');
}
}
Parent.tell(); // // tell
}
// 靜態(tài)屬性
{
class Parent{
constructor(name='mukewang'){
this.name=name;
}
static tell(){
console.log('tell');
}
}
Parent.type='test'; // 靜態(tài)屬性,直接在類上定義即可奥邮,注意不是實(shí)例
console.log('靜態(tài)屬性',Parent.type); // 靜態(tài)屬性 test
}
十三万牺、Promise
// 基本定義
{
let ajax=function(callback){
console.log('執(zhí)行');
setTimeout(function () {
callback&&callback.call()
}, 1000);
};
ajax(function(){
console.log('timeout1'); // 執(zhí)行 timeout1
})
}
{
let ajax=function(){
console.log('執(zhí)行2');
return new Promise(function(resolve,reject){
setTimeout(function () {
resolve()
}, 1000);
})
};
ajax().then(function(){
console.log('promise','timeout2'); // 執(zhí)行2 promise timeout2
})
}
{
let ajax=function(){
console.log('執(zhí)行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');
})
}
{
let ajax=function(num){
console.log('執(zhí)行4');
return new Promise(function(resolve,reject){
if(num>5){
resolve()
}else{
throw new Error('出錯(cuò)了')
}
})
}
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);
});
}
// Promise.all 所有圖片加載完再添加到頁面
{
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);
})
}
// 把多個(gè)promise作為一個(gè)promise實(shí)例
Promise.all([
loadImg('http://i4.buimg.com/567571/df1ef0720bea6832.png'),
loadImg('http://i4.buimg.com/567751/2b07ee25b08930ba.png'),
loadImg('http://i2.muimg.com/567751/5eb8190d6b2a1c9c.png')
]).then(showImgs)
}
// Promise.race 有一個(gè)圖片加載完就添加到頁面
{
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('http://i4.buimg.com/567571/df1ef0720bea6832.png'),
loadImg('http://i4.buimg.com/567751/2b07ee25b08930ba.png'),
loadImg('http://i2.muimg.com/567751/5eb8190d6b2a1c9c.png')
]).then(showImgs)
}
promise中使用map
let data = [1, 2, 3, 4, 5, 6]
Promise.all(data.map((arr) => {
console.log("arr", arr)
return new Promise(function(resolve, reject) {
setTimeout(() => {
console.log("arr-set", 1)
resolve(2)
}, 2000)
})
})).then(res => {
console.log('res', res)
})
十四罗珍、iterator和for...of循環(huán)
// iterator用法
{
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: "world", 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(){
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
}
}
十五、Generator,一種異步編程解決方案
JavaScript 代碼運(yùn)行時(shí)脚粟,會(huì)產(chǎn)生一個(gè)全局的上下文環(huán)境(context覆旱,又稱運(yùn)行環(huán)境),包含了當(dāng)前所有的變量和對(duì)象核无。然后扣唱,執(zhí)行函數(shù)(或塊級(jí)代碼)的時(shí)候,又會(huì)在當(dāng)前上下文環(huán)境的上層团南,產(chǎn)生一個(gè)函數(shù)運(yùn)行的上下文噪沙,變成當(dāng)前(active)的上下文,由此形成一個(gè)上下文環(huán)境的堆棧(context stack)吐根。
這個(gè)堆棧是“后進(jìn)先出”的數(shù)據(jù)結(jié)構(gòu)正歼,最后產(chǎn)生的上下文環(huán)境首先執(zhí)行完成,退出堆棧拷橘,然后再執(zhí)行完成它下層的上下文局义,直至所有代碼執(zhí)行完成,堆棧清空冗疮。
Generator 函數(shù)不是這樣萄唇,它執(zhí)行產(chǎn)生的上下文環(huán)境,一旦遇到y(tǒng)ield命令术幔,就會(huì)暫時(shí)退出堆棧另萤,但是并不消失,里面的所有變量和對(duì)象會(huì)凍結(jié)在當(dāng)前狀態(tài)诅挑。等到對(duì)它執(zhí)行next命令時(shí)四敞,這個(gè)上下文環(huán)境又會(huì)重新加入調(diào)用棧,凍結(jié)的變量和對(duì)象恢復(fù)執(zhí)行揍障。
// genertaor基本定義
{
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}
}
// genertaor與iterator
{
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
}
}
// 狀態(tài)機(jī)
{
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}
}
// async await寫法目养,效果同上,它是Generator的語法糖
// {
// let state=async function (){
// while(1){
// await 'A';
// await 'B';
// await 'C';
// }
// }
// let status=state();
// console.log(status.next());
// console.log(status.next());
// console.log(status.next());
// console.log(status.next());
// console.log(status.next());
// }
// 實(shí)例
// 抽獎(jiǎng)
{
let draw=function(count){
//具體抽獎(jiǎng)邏輯
console.info(`剩余${count}次`)
}
let residue=function* (count){
while (count>0) {
count--;
yield draw(count);
}
}
let star=residue(5);
let btn=document.createElement('button');
btn.id='start';
btn.textContent='抽獎(jiǎng)';
document.body.appendChild(btn);
document.getElementById('start').addEventListener('click',function(){
star.next();
},false)
}
// 長輪詢(服務(wù)端某個(gè)數(shù)據(jù)定期變換毒嫡,前端需要定時(shí)去取這個(gè)狀態(tài))
{
let ajax=function* (){
yield new Promise(function(resolve,reject){
setTimeout(function () {
resolve({code:0})
}, 200);
})
}
let pull=function(){
let genertaor=ajax();
let step=genertaor.next();
step.value.then(function(d){
if(d.code!=0){
setTimeout(function () {
console.info('wait');
pull()
}, 1000);
}else{
console.info(d);
}
})
}
pull();
}
十六、Decorator 修飾器是一個(gè)函數(shù)幻梯,用來修改類的行為
{
let readonly=function(target,name,descriptor){ // 第一個(gè)參數(shù)修改的類本身兜畸,第二個(gè)參數(shù)是修改的屬性名稱,第三個(gè)是該屬性的描述對(duì)象
descriptor.writable=false; // 把屬性描述對(duì)象的寫屬性置為false
return descriptor
};
class Test{
@readonly
time(){
return '2017-03-11'
}
}
let test=new Test();
// test.time=function(){
// console.log('reset time'); // Cannot assign to read only property 'time' of object '#<Test>' 不允許修改只讀屬性
// };
console.log(test.time()); // 2017-03-11
}
{
let typename=function(target,name,descriptor){
target.myname='hello';
}
@typename // 在類里面和類外邊寫都可以
class Test{
}
console.log('類修飾符',Test.myname); // 類修飾符 hello
// 第三方庫修飾器的js庫:core-decorators; npm install core-decorators
}
// 實(shí)例,埋點(diǎn)
{
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.info('ad is show')
}
@log('click')
click(){
console.info('ad is click');
}
}
let ad=new AD();
ad.show(); // ad is show log show
ad.click(); // ad is click log click
}
十七碘梢、module
// 第一種寫法
// export let A=123;
// export function test(){
// console.log('test');
// }
// export class Hello{
// test(){
// console.log('class');
// }
// }
// 第二種寫法
let A=123;
let test=function(){
console.log('test');
}
class Hello{
test(){
console.log('class');
}
}
export default {
A,
test,
Hello
}
export function test () {} // 第一種
const test = function () {}
const gogo = function () {}
export {
test,
gogo
}
export default {test,gogo}
import {test,gogo} from "index.js"
import data from "index.js"
data.test();
十八咬摇、let,const
es6是在嚴(yán)格模式下的 let,const是塊級(jí)作用域煞躬,沒有變量提升
// 1.const不能被改變
// 2.const更符合函數(shù)式編程
// 3.js對(duì)let與const內(nèi)部處理機(jī)制不同肛鹏,const更加優(yōu)化
let,const聲明的變量是在一個(gè)叫script作用域下的逸邦,而var聲明的變量因?yàn)樽兞刻嵘蕴嵘搅巳肿兞縲indow對(duì)象中,這使我們能放心的使用新語法在扰,不用擔(dān)心污染全局的window對(duì)象
for循環(huán)用var缕减,var只執(zhí)行一次,用let,let執(zhí)行次數(shù)等于循環(huán)次數(shù)
// 將類似于數(shù)組的東西轉(zhuǎn)換為數(shù)組
const s = "1234"
const result = Array.from(s)
console.log(result)
// NaN與NaN不相等芒珠,如果想要想等需要采用以下方法
console.log(NaN === NaN);
console.log(Object.is(NaN, NaN));