es6入門

一燃领、解構(gòu)賦值

  1. 數(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ò)展

  1. 箭頭函數(shù)沒有arguments(建議使用更好的語法男应,剩余運(yùn)算符替代)
  2. 箭頭函數(shù)沒有prototype屬性游桩,沒有constructor薪铜,即不能用作與構(gòu)造函數(shù)(不能用new關(guān)鍵字調(diào)用)
  3. 箭頭函數(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));


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末桥狡,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子皱卓,更是在濱河造成了極大的恐慌裹芝,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,104評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件娜汁,死亡現(xiàn)場離奇詭異嫂易,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)掐禁,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,816評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門怜械,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人穆桂,你說我怎么就攤上這事宫盔。” “怎么了享完?”我有些...
    開封第一講書人閱讀 168,697評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵灼芭,是天一觀的道長。 經(jīng)常有香客問我般又,道長彼绷,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,836評(píng)論 1 298
  • 正文 為了忘掉前任茴迁,我火速辦了婚禮寄悯,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘堕义。我一直安慰自己猜旬,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,851評(píng)論 6 397
  • 文/花漫 我一把揭開白布倦卖。 她就那樣靜靜地躺著洒擦,像睡著了一般。 火紅的嫁衣襯著肌膚如雪怕膛。 梳的紋絲不亂的頭發(fā)上熟嫩,一...
    開封第一講書人閱讀 52,441評(píng)論 1 310
  • 那天,我揣著相機(jī)與錄音褐捻,去河邊找鬼掸茅。 笑死椅邓,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的昧狮。 我是一名探鬼主播景馁,決...
    沈念sama閱讀 40,992評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼陵且!你這毒婦竟也來了裁僧?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,899評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤慕购,失蹤者是張志新(化名)和其女友劉穎聊疲,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體沪悲,經(jīng)...
    沈念sama閱讀 46,457評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡获洲,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,529評(píng)論 3 341
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了殿如。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片贡珊。...
    茶點(diǎn)故事閱讀 40,664評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖涉馁,靈堂內(nèi)的尸體忽然破棺而出门岔,到底是詐尸還是另有隱情,我是刑警寧澤烤送,帶...
    沈念sama閱讀 36,346評(píng)論 5 350
  • 正文 年R本政府宣布寒随,位于F島的核電站,受9級(jí)特大地震影響帮坚,放射性物質(zhì)發(fā)生泄漏妻往。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,025評(píng)論 3 334
  • 文/蒙蒙 一试和、第九天 我趴在偏房一處隱蔽的房頂上張望讯泣。 院中可真熱鬧,春花似錦阅悍、人聲如沸好渠。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,511評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽晦墙。三九已至,卻和暖如春肴茄,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背但指。 一陣腳步聲響...
    開封第一講書人閱讀 33,611評(píng)論 1 272
  • 我被黑心中介騙來泰國打工寡痰, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留抗楔,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,081評(píng)論 3 377
  • 正文 我出身青樓拦坠,卻偏偏與公主長得像连躏,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子贞滨,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,675評(píng)論 2 359