//Symbol
//这种数据类型提供一种独一无二的值
//用Symbol声明的值 不相等不重复
{
  //声明
  let a1=Symbol();
  let a2=Symbol();
  console.log(a1===a2);
  let a3=Symbol.for("a3");   //false
  //Symbol.for 都是生成独一无二得值,如果key值注册过就返回这个值,如果没注册过就又生成一个独一无二的值
  let a4=Symbol.for("a3");
  console.log(a3===a4);      //true
}
//Symbol作用和应用场景
{
  let a1=Symbol.for("abc");
  let obj={
    [a1]:"123",
    "abc":345,
    "c":456
  };
  console.log("obj",obj);
  //对象中有用到Symbol做key值,通过let of和都是拿不到key值[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("ownKeys",item,obj[item]);
  })
  //这个都可以拿到
  //ownKeys abc 345
  //ownKeys c 456
  //ownKeys Symbol(abc) 123
}
//数据结构
//Set用法  集合中的元素不能重复
//Map用法  key一定是字符串 可以是任意类型
//WeakSet用法
//WeakMap用法
//在Set里增加元素 用add()方法
{
  let list= new Set();
  list.add(5);
  list.add(7);
//要获取Set的长度得用size属性 相当于length
  console.log("size",list.size);
}
//Set另一种定义方式
{
  let arr= [1,2,3,4,5]
  //然后数组转换成集合了
  let list = new Set(arr);
  console.log("size",list.size);
}
////Set集合中的元素不能重复,必须是唯一的
{//场景应用——去重
  let list = new Set();
  list.add(1);
  list.add(2);
  list.add(1);
  console.log("list",list);
}
//Set数组去重
//不会做数据类型的转换 "2"
//去重要注意元素类型是不是一致
{
  let arr = [1,2,4,5,2,1];
  let list2 = new Set(arr);
  console.log("unique",list2);
}
//添加 删除 清空 包含
{
  let arr=["add","delete","clear","has"];
  let list =new Set(arr);
  console.log("has",list.has("add"));
  console.log("delete",list.delete("add"),list);;
  list.clear();
  console.log("list",list);
}
//对Set的遍历
{
  let arr=["add","delete","clear","has"];
  let list=new Set(arr);
  for(let key of list.keys()){
    console.log(‘keys‘,key);
  }
  for(let value of list.values()){
    console.log(‘value‘,value);
  }
  for(let [key,value] of list.entries()){
    console.log(‘entries‘,key,value);
  }
  list.forEach(function(item){console.log(item);})
}
//WeakSet支持的数值必须是对象
//添加对象 是地址的引用
//没有clear方法
//没有size属性
//不能遍历
{
  let weakList=new WeakSet();
let arg={};
weakList.add(arg);
  // weakList.add(2);
  //数字会报错 不是 对象
  console.log(‘weakList‘,weakList);
}
//Map
//Map添加元素是用set
//Map的key可以是任意类型 eg arr
{
  let map = new Map();
  let arr=[‘123‘];
map.set(arr,456);
  console.log(‘map‘,map,map.get(arr));
  //获取值是用get
}
//Map的第二种定义方式
{
  let map = new Map([[‘a‘,123],[‘b‘,456]]);
  console.log(‘map args‘,map);
  //常用的属性值和方法
  //获取 get 添加set
  console.log(‘size‘,map.size); //长度
  console.log(‘delete‘,map.delete(‘a‘),map); //删除
  console.log(‘clear‘,map.clear(),map); //清空
}
//WeakMap接收的key值必须是对象
//没有clear方法
//没有size属性
//不能遍历
{
  let weakmap=new WeakMap();
  let o={};
  weakmap.set(o,123);
  console.log(weakmap.get(o));
}
//Map和Set横向对比
//数据结构横向对比 增删查改
//能使用Map不适用数组 优先Map
//保证数字的唯一性 用Set
//Map和array对比
{
  let map = new Map();
  let array=[];
  //增
  map.set("t",1);
  array.push({t:1});
  console.info("map-array",map,array);
  //删
  map.delete("t");
  //es5中对索引查询
  let index=array.findIndex(item=>item.t);
  array.splice(index,1);
  console.info("map-delete",map,array);
  //查
  let map_exist=map.has("t");
  let array_exist=array.find(item=>item.t);
  console.info("map-exist",map_exist,array);
  //改
  map.set("t",2);
  //遍历,判断值是否存在,
  array.forEach(item=>item.t?item.t=2:"");
  console.info("map-change",map,array);
}
//Set和array对比
{
  let set=new Set();
  let array=[];
  //增
  set.add({t:1});
  array.push({t:1});
console.info("set-array",set,array);
  //删
  set.forEach(item=>item.t?set.delete(item):"");
  let index=array.findIndex(item=>item.t);
  array.splice(index,1);
  console.info("set-delete",set,array);
  //查
  let set_exist=set.has({t:1});
  let array_exist=array.find(item=>item.t);
  console.info("set-exist",set_exist,array_exist);
  //改
  set.forEach(item=>item.t?item.t=2:"");
  array.forEach(item=>item.t?item.t=2:"");
  console.info("set-change",set,array);
}
//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-add",obj,map,set);
  //删
  map.delete("t");
  //map使用成本最低
  set.delete(item);
  //set还需要forEach
  delete obj["t"];
  console.info("map-set-obj-delete",obj,map,set);
  //查
  console.info({
    map_exist:map.has("t"),
    set_exist:set.has(item),
    obj_exist:"t" in obj
  })
  //改
  map.set("t",2);
  obj["t"]=2;
  console.info("map-set-obj-change",obj,map,set);
}
//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");
    },
    //get就是拦截所有和读取相关的属性
    //拦截对象属性的设置
    //set指的代理
    set(target,key,value){
      //只允许你修改name这个属性
      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
    //过滤掉time属性
    ownKeys(target){
      return Object.keys(target).filter(item=>item!=‘time‘)
    }
  });
  console.log("get",monitor.time);
  //输出结果是2018-03-11 通过代理的作用
  // . 就是从monitor对象中读取time
  monitor.time="2019";
  console.log("set",monitor.time);
  //修改失败 因为是允许修改name
  monitor.name="925";
  console.log("set",monitor.time,monitor);
  console.log("has","name" in monitor); //true
  console.log("has","time" in monitor); //false 通过代理欺骗了用户
  // delete monitor.time;
  // console.log("delete",monitor);
  // delete monitor._r;
  // console.log("delete",monitor);
   console.log(‘ownKeys‘,Object.keys(monitor));
}
//monitor——传给Proxy——再给obj
//Reflect
{
  let obj={
    time:‘2017-03-11‘,
    name:‘net‘,
    _r:123
  };
  console.log(‘Reflect get‘,Reflect.get(obj,‘time‘));
  Reflect.set(obj,‘name‘,‘milk‘);
  console.log(obj);
  console.log(‘has‘,Reflect.has(obj,‘name‘));
}
//类的概念
// 基本定义和生成实例
 {
  class Parent{
    constructor(name=‘mukewang‘){
      //构造函数
      this.name=name;
    }
  }
  let v_parent=new Parent(‘v‘);
  console.log(‘构造函数和实例‘,v_parent);
}
{
  // 继承
  class Parent{
    constructor(name=‘mukewang‘){
      this.name=name;
    }
  }
  class Child extends Parent{
    
  }
  console.log(‘继承‘,new Child());
}
//子类把参数传递给父类——super
//子类参数如果是空 默认使用父类的默认值
//子类如果增加自己的属性,一定要在super后面
{
  // 继承传递参数
  class Parent{
    constructor(name=‘mukewang‘){
      this.name=name;
    }
  }
  class Child extends Parent{
    constructor(name=‘child‘){
      super(name);
      //super要在第一行
      this.type=‘child‘;
    }
  }
  console.log(‘继承传递参数‘,new Child(‘hello‘));
}
{
  // getter,setter
  class Parent{
    constructor(name=‘mukewang‘){
      this.name=name;
    }
    get longName(){
      return ‘mk‘+this.name
    }
    set longName(value){
      this.name=value;
    }
  }
   let v=new Parent();
  console.log(‘getter‘,v.longName);
  //setter赋值
  v.longName=‘hello‘;
  console.log(‘setter‘,v.longName);
}
//类的静态方法  static 通过类去调用 而不是通过类的实例去调用
{
  // 静态方法
  class Parent{
    constructor(name=‘mukewang‘){
      this.name=name;
    }
    static tell(){
      console.log(‘tell‘);
    }
  }
Parent.tell();
}
{
  // 静态属性
  class Parent{
    constructor(name=‘mukewang‘){
      this.name=name;
    }
    static tell(){
      console.log(‘tell‘);
    }
  }
//直接在类上定义
  Parent.type=‘test‘;
console.log(‘静态属性‘,Parent.type);
}
//Promise 异步
//Promise的作用
//基本用法
//es5回调
{
  // 基本定义
  let ajax=function(callback){
    console.log(‘执行‘);
    setTimeout(function () {
      callback&&callback.call()
    }, 1000);
  };
  ajax(function(){
    console.log(‘timeout1‘);
  })
}
//promise
{
  let ajax=function(){
    console.log(‘执行2‘);
    return new Promise(function(resolve,reject){
      setTimeout(function () {
        resolve()
      }, 1000);
    })
  };
  ajax().then(function(){
    console.log(‘promise‘,‘timeout2‘);
  })
}
{
  let ajax=function(){
    console.log(‘执行3‘);
    return new Promise(function(resolve,reject){
      setTimeout(function () {
        resolve()
      }, 1000);
    })
  };
  ajax()
    .then(function(){
    return new Promise(function(resolve,reject){
      setTimeout(function () {
        resolve()
      }, 2000);
    });
  })
    .then(function(){
    console.log(‘timeout3‘);
  })
}
//捕获错误 catch
{
  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高级用法 加载图片
//Promise,all 把多个Promise实例当成一个
//就是所有的发生变化 才会触发Promise.all
//Promise.race
//先到先得 有一个率先改变就改变 其他的就不再响应了
原文:http://www.cnblogs.com/yishichangan925/p/7745965.html