• ES6解析*项目学习记录(三)


    10. Set - Map 数据结构

    Set 的概念

    * set 类似数组,集合中的元素不能重复
    * map 类似对象,key值任意数据类型
    {
      let list = new Set();
      //增加元素的方法
      list.add(5);
      list.add(7);
    
      //获取长度
      console.log(list.size); //2
    }

     Set 的转换

    {
      // 将数组转换为 Set 集合
      let arr = [1, 2, 3, 4, 5];
      let list = new Set(arr);
    
      console.log(list.size); //5
    }
    
    {
      let list = new Set();
      list.add(1);
      list.add(2);
      // 不生效
      list.add(1);
      console.log(list); //Set(2) {1, 2}
    }

    数组去重

    {
      //数组去重, 但不能过滤数据类型
      let arr = [1, 3, 3, 4, 5, 7, 7, 7];
      let list2 = new Set(arr);
      console.log(list2); //Set(5) {1, 3, 4, 5, 7}
      console.log([...list2]); //[1, 3, 4, 5, 7]
    }

    常用API

    {
      //常用API
      let arr = ["add", "delete", "clear", "has"];
      let list = new Set(arr);
      // 包含
      console.log(list.has("add")); //true
      // 删除
      console.log(list.delete("add"), list); //true , Set(3) {"delete", "clear", "has"}
      // 清空
      list.clear();
      console.log(list); //Set(0) {}
    }

    遍历

     let...of

      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("values", value);
        // values add
        // values delete
        // values clear
        // values has
      }
      for (let value of list) {
        console.log("list", value);
        // list add
        // list delete
        // list clear
        // list has
      }
      for (let [key, value] of list.entries()) {
        console.log("entris", key, value);
        // entris add add
        // entris delete delete
        // entris clear clear
        // entris has has
      }

    forEach 

      list.forEach(item => {
        console.log(item);
        // add
        // delete
        // clear
        // has
      });
    结论: Set 的 key 和 value 都是一样的,都是元素的名称

    WeakSet

    • 和 Set 支持的数据类型不一样, 元素只能是对象
    • 对象都是弱引用,不是值拷贝,而是地址引用。不会和垃圾回收机制挂钩
    • 没有clear 方法,没有size属性,不能遍历
    {
      let weakList = new WeakSet();
      let arg = {};
      weakList.add(arg);
      // weakList.add(2); //Invalid value used in weak set
      console.log(weakList); //WeakSet {{…}}
      console.log(weakList.size); //undefined
    }

    Map

    // 声明
    {
      let map = new Map();
      let arr = ["123"];
    
      //添加元素用set, 获取用get
      map.set(arr, 456);
      console.log(map, map.get(arr)); //Map {["123"] => 456} 456
    }
    
    {
      // 参数:内方括号代表一个元素,内部为 key value
      let map = new Map([["a", 123], ["b", 456]]);
      console.log(map); //Map(2) {"a" => 123, "b" => 456}
    }

    常用属性方法,基本同Set

    {
      let map = new Map([["a", 123], ["b", 456]]);
    
      console.log(map.size); //2
      console.log(map.delete("a"), map); //true Map(1) {"b" => 456}
      console.log(map.clear());
      console.log(map); //Map(0) {}
    }

    Map 的遍历和 Set 一模一样

    WeakMap

    •  key 值 必须是对象
    • 没有 size 不能使用 clear
    • 不能遍历
    {
      let weakmap = new WeakMap();
      let o = {};
      weakmap.set(o, 123);
      console.log(weakmap, weakmap.get(o)); //WeakMap {{...} => 123} 123
    }

    map-set 与 数组和对象的比较

    map 与数组
    {
      // 数据结构的横向对比 增、查、改、删
      let map = new Map();
      let array = [];
    
      //
      map.set("t", 1);
      array.push({ t: 1 });
      console.info("map-array-add", map, array);
      //Map(1) {"t" => 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);
      // true  {t:1}
    
      //
      map.set("t", 2);
      array.forEach(item => (item.t ? (item.t = 2) : ""));
      console.info("map-array-modify", map, array);
      //Map(1) {"t" => 2}
      //[{t:2}]
    
      //
      map.delete("t");
      let index = array.findIndex(item => item.t);
      array.splice(index, 1);
      console.info("map-array-empty", map, array);
      //Map(0) {}
      //[]
    }

    set与数组

    {
      let set = new Set();
      let array = [];
      //
      set.add({ t: 1 });
      array.push({ t: 1 });
      console.info("set-array", set, array);
      // Set(1) {{t:1}}
      // [{t:1}]
    
      //
      let set_exist = set.has({ t: 1 }); //因为是引用地址
      let array_exist = array.find(item => item.t); //返回这个值
      console.info("set-array", set_exist, array_exist);
      //false {t:1}
    
      //
      set.forEach(item => (item.t ? (item.t = 2) : ""));
      array.forEach(item => (item.t ? (item.t = 2) : ""));
      console.log("set-array-modify", set, array);
      // Set(1) {{t:2}}
      // [{t:2}]
    
      //
      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(0) {}
      //[]
    }
    Map set 与 对象
    {
      //Map set 与 对象
      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.log("map-set-obj", map, set, obj);
      // Map(1) {"t" => 1}   Set(1) {{t:1}}   {t: 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.log("map-set-obj-modify", map, set, obj);
      //Map(1) {"t" => 2}   Set(1) {{t: 2}}  {t: 2}
    
      //
      map.delete("t");
      set.delete(item);
      delete obj["t"];
      console.log("map-set-obj-empty", map, set, obj);
      //Map(0) {}   Set(0) {}   {}
    }

    总结:

    * 能使用Map 不使用 数组,有数据结果存储唯一性应考虑 Set

     11. Proxy(代理) Reflect(反射)

    • 连接用户和原始对象的层
    • 为操作Object提供新的Api
    • 二者方法是一样的
    {
      //供应商 也是原始对象
      let obj = {
        time: "2018-07-08",
        name: "net",
        _r: 123
      };
    
      //代理商 Proxy对象
      let monitor = new Proxy(obj, {
        //拦截对象属性的读取
        get(target, key) {
          return target[key].replace("2018", "2019");
        },
        //拦截对象属性的设置
        set(target, key, value) {
          if (key === "name") {
            return (target[key] = value);
          } else {
            return target[key];
          }
        },
        //拦截当前对象是否拥有某个属性
        has(target, key) {
          if (key === "name") {
            return target[key];
          } else {
            return false;
          }
        },
        //拦截对象 删除属性
        deleteProperty(target, key) {
          if (key.indexOf("_") > -1) {
            delete target[key];
            return true;
          } else {
            return target[key];
          }
        },
        //拦截Object.keys, Object.getOwnPropertySymbols, Object.getOwnPropertyNames
        ownKeys(target) {
          //保护 time 属性
          return Object.keys(target).filter(item => item != "time");
        }
      });
    
      //用户而言 是直接操作monitor对象
      console.log("get", monitor.time); //2019-07-08
      monitor.name = "qqq";
      console.log("set", monitor.name, monitor); //qqq  Proxy {time: "2018-07-08", name: "qqq", _r: 123}
      console.log("has", "name" in monitor, "time" in monitor); //true  false
      // delete monitor.time;
      // console.log("delete", monitor); //Proxy {time: "2018-07-08", name: "qqq", _r: 123}
      // delete monitor._r;
      // console.log("delete", monitor); //Proxy {time: "2018-07-08", name: "qqq"}
      console.log("ownKeys", Object.keys(monitor)); // ["name", "_r"]
    }
    Reflect 用法和 Proxy 一样
    {
      let obj = {
        time: "2018-07-08",
        name: "net",
        _r: 123
      };
    
      console.log("Reflect get", Reflect.get(obj, "time")); //2018-07-08
      Reflect.set(obj, "name", "mukewang");
      console.log(obj); //{time: "2018-07-08", name: "mukewang", _r: 123}
      console.log(Reflect.has(obj, "name")); //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);
              } 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;
        }
      };
      class Person {
        constructor(name, age) {
          this.name = name;
          this.age = age;
          return validator(this, personValidators);
        }
      }
    
      const person = new Person("lili", 30);
    
      console.log(person); //Proxy {name: "lili", age: 30}
    
      // person.name = 48; //报错 Uncaught Error: 不能设置name到48
      person.name = "abc";
      console.log(person); //Proxy {name: "abc", age: 30}
    }

     12. CLASS 类

    基本定义及生成实例

    {
      //基本定义及生成实例
      class Parent {
        constructor(name = "muke") {
          this.name = name;
        }
        tell() {
          console.log("tell");
        }
      }
      let v_parnet = new Parent("qqq");
      console.log(v_parnet); //Parent {name: "qqq"}
      v_parnet.tell(); //tell
    }

    继承

    {
      //继承
      class Parent {
        constructor(name = "muke") {
          this.name = name;
        }
      }
    
      // 继承父类
      class Child extends Parent {}
    
      console.log(new Child()); //Child {name: "muke"}
    }
    
    {
      //继承传递参数
      class Parent {
        constructor(name = "muke") {
          this.name = name;
        }
      }
    
      // 子类向父类传递参数
      class Child extends Parent {
        constructor(name = "child") {
          //调用super方法,得到子类的this对象
          //super 指向父类,相当于 A.prototype.constructor.call(this)
          super(name);
          //定义自己的属性一定要放在super之后
          this.type = "child";
        }
      }
    
      console.log(new Child("hello")); //_Child {name: "hello", type: "child"}
    }

    getter setter

    {
      //getter setter
      class Parent {
        constructor(name = "muke") {
          this.name = name;
        }
        //属性 不是函数
        get longName() {
          return "mk" + this.name;
        }
        set longName(value) {
          this.name = value;
        }
      }
      let v = new Parent();
      console.log("getter", v.longName); //mkmuke
      // 赋值就等于 set 操作
      v.longName = "hello";
      console.log("setter", v.longName); //mkhello
    }

    静态方法 与 静态属性

    {
      // 静态方法 与 静态属性
      class Parent {
        constructor(name = "muke") {
          this.name = name;
        }
        //静态方法是通过类去调用,而不是通过类的实例去调用
        static tell() {
          console.log("tell");
        }
      }
      // 直接定义静态属性
      Parent.type = "test";
      Parent.tell(); //tell
      console.log("静态属性", Parent.type); //test
    }

    13. Promise-异步编程的解决方案

    异步A执行完去执行B,传统方式:回调,事件触发
    {
      //ES5中回调
      let ajax = function(callback) {
        console.log("执行");
        setTimeout(() => {
          callback && callback.call();
        }, 1000);
      };
      ajax(function() {
        console.log("timeout1");
        //执行
        //timeout1
      });
    }
    //ES6 Promise
    {
      let ajax = function() {
        console.log("执行2");
        return new Promise(function(resolve, reject) {
          setTimeout(() => {
            resolve();
          }, 1000);
        });
      };
    
      ajax().then(function() {
        console.log("timeout2");
        //执行2
        //timeout2
      });
    }
    {
      let ajax = function() {
        console.log("执行3");
        return new Promise(function(resolve, reject) {
          setTimeout(() => {
            resolve();
          }, 1000);
        });
      };
    
      ajax()
        .then(function() {
          return new Promise(function(resolve, reject) {
            setTimeout(() => {
              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", 6);
      //   })
      //   .catch(function(err) {
      //     console.log("catch", err);
      //   }); // catch Error: 出错
    }

    一些应用

    {
      //所有图片加载完成再添加到页面
      function loadImg(src) {
        return new Promise(function(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.all([
        loadImg(
          "http://img.mp.itc.cn/upload/20160415/43ba06629ee0493cb6784a7455cb5cc5.jpg"
        ),
        loadImg("http://img.duoziwang.com/2018/06/2018010154139925.jpg"),
        loadImg(
          "http://img.mp.itc.cn/upload/20160415/59cca1073eaa49788e349c67e4a9c37e.jpg"
        )
      ]).then(showImgs);
    }
    {
      //有一个图片加载完成就添加到页面
      function loadImg(src) {
        return new Promise(function(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);
      }
      //有一个状态改变,race实例也跟着改变
      Promise.race([
        loadImg(
          "http://img.mp.itc.cn/upload/20160415/43ba06629ee0493cb6784a7455cb5cc5.jpg"
        ),
        loadImg("http://img.duoziwang.com/2018/06/2018010154139925.jpg"),
        loadImg(
          "http://img.mp.itc.cn/upload/20160415/59cca1073eaa49788e349c67e4a9c37e.jpg"
        )
      ]).then(showImgs);
    }
  • 相关阅读:
    3年A班,从现在起大家都是人质-观后感
    深入浅出的Object.defineProperty()
    在Vue中使用插槽(solt)
    非父子组件间的传值
    给组件绑定原生事件
    组件参数校验与非props特性
    Vue父子组件的数据传递
    Vue组件使用中的细节点
    vue中set基本用法
    vue中的列表渲染
  • 原文地址:https://www.cnblogs.com/anqwjoe/p/11175003.html
Copyright © 2020-2023  润新知