es6入门

作者: zxhnext | 来源:发表于2019-03-20 22:13 被阅读0次

一、解构赋值

  1. 数组的解构赋值
{
  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
}
// 应用场景
// 变量交换
{
  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]
}

二、 对象解构赋值

{
  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
}

// 应用场景
{
  let metaData = {
    title: 'abc',
    test:[{
      title: 'test',
      desc: 'description'
    }]
  }
  let {title:esTitle,test:[{title:cnTitle}]} = metaData
  console.log(esTitle,cnTitle) // abc test
}

// 对象内写函数时不需要再加function,而且对象内支持变量
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("!")) // 以什么结束
console.log(c.includes("family")) // 包含什么

const c = test `${a} ${b} 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中后面的修饰符会覆盖掉前面的修饰符
  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); // 判断正则对象是否开启了y修饰符 false true
}

// u修饰符
{
  console.log('u-1',/^\uD83D/.test('\uD83D\uDC2A')); // \uD83D\uDC2A当作两个字符
  console.log('u-2',/^\uD83D/u.test('\uD83D\uDC2A')); // \uD83D\uDC2A当作一个字符

  console.log(/\u{61}/.test('a')); // false
  console.log(/\u{61}/u.test('a')); // true

  console.log(/\u{20BB7}/u.test('𠮷')); // true
  // 点(.)字符不能识别码点大于0xFFFF的Unicode字符,必须加上u修饰符。
  let s = '𠮷';
  console.log('大于0xFFFF的Unicode字符',/^.$/.test(s)); // false
  console.log('使用u字符',/^.$/u.test(s)); // true

  // 使用u修饰符后,所有量词都会正确识别大于码点大于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  
}

{
  // #正则表达式中,点(.)是一个特殊字符,代表任意的单个字符,但是行终止符(line terminator character)除外
  // U+000A 换行符(\n)
  // U+000D 回车符(\r)
  // U+2028 行分隔符(line separator)
  // U+2029 段分隔符(paragraph separator)
  // 只是一个提案目前还不支持
  // 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'));
}

四、字符串扩展

// 字符串扩展

// 处理unicode编码处理大于0xFFFF
{
  console.log('a', '\u0061'); // a a
  console.log('s', '\u20BB7'); // s ₻7 \u20BB7太长,被当成了\u20BB和7两个字符
  console.log('s', '\u{20BB7}'); // s 𠮷 es6方法,将字符集用{}包起来
}

{
  let s = '𠮷';
  console.log('length',s.length) // 2 码值大于两个字节,所以当作4个字节处理,两个字节为1个长度
  console.log('0',s.charAt(0)); // 0 � 取第一个位置的字符
  console.log('1',s.charAt(1)); // 1 �
  console.log('at0',s.charCodeAt(0)); // at0 55362 // 取第一个位置的码值
  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 
}

// 转换为字符
{
  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
}

// 重复
{
  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 第一个参数是长度,第二个是补什么 比如日期小于10月补0
  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); // ["i am ", ",", "", raw: Array(3)] "list" "hello world"
    return s+v1+v2
  }
}

// String.raw对所有字符串进行转译
{
  console.log(String.raw`Hi\n${1+2}`); // Hi\n3
  console.log(`Hi\n${1+2}`); // Hi 3
}

五、数值扩展

// es6中二进制以0B开头,八进制以0o开头,大小写都可以
{
  console.log('B',0B111110111);
  console.log(0o767);
}

{
  // 是否有尽之内
  console.log('15',Number.isFinite(15)); // true
  console.log('NaN',Number.isFinite(NaN)); // false
  console.log('1/0',Number.isFinite('true'/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
  console.log('25.1',Number.isInteger(25.1)); // false
  console.log('25',Number.isInteger('25')); // false
}

// 判断一个数是否在-2^53与2^53之间,超过这个范围数就不准了
{
  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
}

// 返回一个小数的整数部分
{
  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('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
}

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

// 三角函数,对数,查api

六、数组扩展

// of把一组数据变量转化为数据类型
{
  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把类数组转化为数组
{
  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() 返回数组下标的集合
    console.log('keys',index); // 0 1 2
  }
  for(let value of ['1','c','ks'].values()){ // values() 返回数组值
    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
  }  
}

// 当前数组内部改变位置
{
  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 返回第一个值
  console.log([1,2,3,4,5,6].findIndex(function(item){return item>3})); // 返回第一个下标
}

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

七、函数扩展

  1. 箭头函数没有arguments(建议使用更好的语法,剩余运算符替代)
  2. 箭头函数没有prototype属性,没有constructor,即不能用作与构造函数(不能用new关键字调用)
  3. 箭头函数没有自己this,它的this是词法的,引用的是上下文的this,即在你写这行代码的时候就箭头函数的this就已经和外层执行上下文的this绑定了(这里个人认为并不代表完全是静态的,因为外层的上下文仍是动态的可以使用call,apply,bind修改,这里只是说明了箭头函数的this始终等于它上层上下文中的this)
// 参数默认值
{
  function test(x, y = 'world'){ // 有默认值的参数后面不可以再声明没有默认值的参数 x, y = 'world', c是错误的
    console.log('默认值',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');
}

// 展开运算符
{
  console.log(...[1,2,4]); // 1 2 4
  console.log('a',...[1,2,4]); // a 1 2 4
}

// 箭头函数
{
  let arrow = v => v*2;
  let arrow2 = () => 5;
  console.log('arrow',arrow(3)); // 6
  console.log(arrow2()); // 5
}

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

八、对象扩展

{
  // 简洁表示法
  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={
    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('数组',Object.is([],[]),[]===[]); // 数组 false false

  // 注意这个是浅拷贝,浅拷贝只拷贝引用地址
  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]); // ["k", 123] ["o", 456]
  }
}

{
  // 扩展运算符 babel支持不好,会报错,实践中暂时没法用
  // 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会查找全局中是否有a3,如果有,取a3的值,如果没有,会执行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"}

  // 遍历的时候是拿不到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
  })  
}

十、数据结构(set, map)

// set中的内容不可重复
{
  let list = new Set();
  list.add(5);
  list.add(7);
  // 数组长度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
  }
  // 默认就是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支持的数据类型不同,只能是对象,并且是弱引用,只拷贝引用地址,他没有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对object的补充,key可以事任何东西,object的key是字符串
{
  let map = new Map();
  let arr=['123'];
  // 用数组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区别相同
{
  let weakmap=new WeakMap();
  let o={};
  weakmap.set(o,123);
  console.log(weakmap.get(o)); // 123
}

// 数据结构横向对比,增,查,改,删
// map与array对比
{
  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) {{…}} [{…}]

  // 删
  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('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 保护一些对象
{
  let obj={ // 原始对象
    time:'2017-03-11',
    name:'net',
    _r:123
  };

  // 拦截代理商
  let monitor=new Proxy(obj,{
    // 读
    get(target,key){
      return target[key].replace('2017','2018'); // 把有2017的替换成2018
    },
    // 设置,例如只能修改name,其他不能修改
    set(target,key,value){ // 第一个参数指obj对象,第二个指key,第三个是key值
      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){ // 不能遍历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
}

// 实际应用
{
  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(`不能设置${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; // 不能设置name到48
  person.name='Han mei mei';
  console.info(person); //  Proxy {name: "lilei", age: 30, mobile: "1111"}
}

十二、 类与对象

class MathHandle {
      //
}
console.log(typeof MathHandle) // "function" 
console.log(MathHandle === MathHandle. prototype. constructor) // true
//这种语法糖形式,看起来和实际原理不一样的东西,我个人不太赞同
//形式上强行模仿java C#,却失去了它的本性和个性
// 基本定义和生成实例
{
  class Parent{
    constructor(name='mukewang'){ // 构造函数
      this.name=name;
    }
  }
  let v_parent=new Parent('v');
  console.log('构造函数和实例',v_parent); // 构造函数和实例 Parent {name: "v"}
}

// // 继承
{
  class Parent{
    constructor(name='mukewang'){
      this.name=name;
    }
  }

  class Child extends Parent{

  }

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

// 继承传递参数
{
  class Parent{
    constructor(name='mukewang'){
      this.name=name;
    }
  }

  class Child extends Parent{
    constructor(name='child'){
      super(name); // 如果super()为空,将默认使用父类所有参数值
      this.type='child'; // 自定义的一定要放在super()后面,即super()在第一行
    }
  }

  console.log('继承传递参数',new Child('hello')); // 继承传递参数 _Child {name: "hello", type: "child"}
}

// getter,setter
{
  class Parent{
    constructor(name='mukewang'){
      this.name=name;
    }

    get longName(){ // 这是属性,不是函数,下面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
}

// 静态方法,静态方法通过类取调用而不是通过实例去调用
{
  class Parent{
    constructor(name='mukewang'){
      this.name=name;
    }

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

  Parent.tell(); // // tell

}

// 静态属性
{
  class Parent{
    constructor(name='mukewang'){
      this.name=name;
    }

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

  Parent.type='test'; // 静态属性,直接在类上定义即可,注意不是实例
  console.log('静态属性',Parent.type); // 静态属性 test
}

十三、Promise

// 基本定义
{
  let ajax=function(callback){
    console.log('执行');
    setTimeout(function () {
      callback&&callback.call()
    }, 1000);
  };
  ajax(function(){
    console.log('timeout1'); // 执行 timeout1
  })
}

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

  ajax().then(function(){
    console.log('promise','timeout2'); // 执行2 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');
  })
}

{
  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);
  });
}


// 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);
    })
  }

  // 把多个promise作为一个promise实例
  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 有一个图片加载完就添加到页面
{
  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循环

// 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 代码运行时,会产生一个全局的上下文环境(context,又称运行环境),包含了当前所有的变量和对象。然后,执行函数(或块级代码)的时候,又会在当前上下文环境的上层,产生一个函数运行的上下文,变成当前(active)的上下文,由此形成一个上下文环境的堆栈(context stack)。

这个堆栈是“后进先出”的数据结构,最后产生的上下文环境首先执行完成,退出堆栈,然后再执行完成它下层的上下文,直至所有代码执行完成,堆栈清空。

Generator 函数不是这样,它执行产生的上下文环境,一旦遇到yield命令,就会暂时退出堆栈,但是并不消失,里面的所有变量和对象会冻结在当前状态。等到对它执行next命令时,这个上下文环境又会重新加入调用栈,冻结的变量和对象恢复执行。

// 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
  }
}

// 状态机
{
  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());
// }

// 实例
// 抽奖
{
  let draw=function(count){
    //具体抽奖逻辑
    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='抽奖';
  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 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 修饰器是一个函数,用来修改类的行为

{
  let readonly=function(target,name,descriptor){ // 第一个参数修改的类本身,第二个参数是修改的属性名称,第三个是该属性的描述对象
    descriptor.writable=false; // 把属性描述对象的写属性置为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
}

// 实例,埋点
{
  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是在严格模式下的 let,const是块级作用域,没有变量提升
// 1.const不能被改变
// 2.const更符合函数式编程
// 3.js对let与const内部处理机制不同,const更加优化
let,const声明的变量是在一个叫script作用域下的,而var声明的变量因为变量提升所以提升到了全局变量window对象中,这使我们能放心的使用新语法,不用担心污染全局的window对象
for循环用var,var只执行一次,用let,let执行次数等于循环次数

// 将类似于数组的东西转换为数组
const s = "1234"
const result = Array.from(s)
console.log(result)

// NaN与NaN不相等,如果想要想等需要采用以下方法
console.log(NaN === NaN);
console.log(Object.is(NaN, NaN));


相关文章

网友评论

      本文标题:es6入门

      本文链接:https://www.haomeiwen.com/subject/hxrzmqtx.html