• ES6笔记(6)-- Set、Map结构和Iterator迭代器


    系列文章 -- ES6笔记系列

    搞ES6的人也是够无聊,把JS弄得越来越像Java、C++,连Iterator迭代器、Set集合、Map结构都出来了,不知道说什么好...

    一、简单使用

    1. iterator

    学过C++的人应该知道这是个迭代器对象,拥有一个指针,指向数据结构中的某个成员

    JS中的iterator也有类似的功能,JS内部为一些数据结构实现了iterator迭代器的接口,让我们可以方便的使用

    var [a, b, ...c] = [1, 2, 3, 4];
    
    c // [3, 4]

    如上,解构赋值以及扩展运算符的便利,多亏了内部实现的默认iterator迭代器接口,可以使用其Symbol.iterator属性获得,如

    var arr = [1, 2, 3];
    
    var it = arr[Symbol.iterator]();
    
    it.next() // {done: false, value: 1}
    it.next() // {done: false, value: 2}
    it.next() // {done: false, value: 3}
    it.next() // {done: true, value: undefined}

    上述的iterator接口表现形式过于隐秘,在generator生成器函数中,我们可以看看比较显示的iterator接口调用:

    function* showNumbers() {
        yield 1;
        yield 2;
        yield 3;
    }
    
    var show = showNumbers();
    
    show.next(); // {done: false, value: 1}
    show.next(); // {done: false, value: 2
    show.next(); // {done: true, value: 3}

    通过调用next方法,实现iterator迭代器的遍历

    可见结果输出是一个对象,该对象拥有done这个迭代器是否遍历完成的状态,以及当前指向项的值

    看到这里,结合上述两个例子,应该知道可以通过Symbol.iterator与generator的结合,创建出一个iterator迭代器,比如:

    var obj = {};
    
    obj[Symbol.iterator] = function* () {
      yield 1;
      yield 2;
      yield 3;
    };
    
    [...obj] // [1, 2, 3]

    既然只有done与value两个属性,实现起来应该不是太难,我们可以尝试实现一个基本的iterator

    function myIterator(arr) {
        var nextIndex = 0;
    
        return {
            next: function() {
                return  nextIndex < arr.length
                    ? {
                        value: arr[nextIndex++],
                        done: false
                    }
                    : {
                        value: undefined,
                        done: true
                    }
            }
        }
    }
    
    var it = myIterator(['one', 'two']);
    
    it.next() // {done: false, value: "one"}
    it.next() // {done: true, value: "two"}
    it.next() // {done: true, value: undefined}

    2. Set

    Set是ES6中新引入的数据结构,它类似于数组,但是成员的值都是唯一的,没有重复的值。

    可以通过实例化其构造函数,用来生成Set数据结构,通过.add()方法插入值,通过for...of循环遍历相应值

    var s = new Set();
    
    var arr = [1, 2, 2, 3];
    
    arr.forEach(function(item) {
        s.add(item);
    });
    
    for (var item of s) {
        console.log(item) // 1 2 3
    }

    可见Set自动去除了重复的值,只插入了一个2,由此在去除数组重复值的时候,可以更方便:

    var arr = [1, 2, 2, 3];
    
    
    function unique(arr) {
        return [...new Set(arr)];
    }
    
    unique(arr) // [1, 2, 3]

    不过,要注意的是,Set判断是否重复,是使用到了全等===条件,即类型及值完全相等才摈除,不过NaN是例外

    var arr = [1, 0, '', 3, false, 3, NaN, NaN];
    
    
    function unique(arr) {
        return [...new Set(arr)];
    }
    
    unique(arr) // [1, 0, '', 3, false, NaN]

    set有一些属性和方法:

    • Set.prototype.constructor:构造函数,默认就是Set函数。
    • Set.prototype.size:返回Set实例的成员总数。
    • add(value):添加某个值,返回Set结构本身。
    • delete(value):删除某个值,返回一个布尔值,表示删除是否成功。
    • has(value):返回一个布尔值,表示该值是否为Set的成员。
    • clear():清除所有成员,没有返回值。
    var s = new Set();
    
    s.add(1).add(2).add(2);
    
    s.size // 2
    
    s.has(1) // true
    s.has(2) // true
    s.has(3) // false
    
    s.delete(2);
    s.has(2) // false
    
    s.clear()
    s.has(1) // false

    set的一些遍历操作:

    • keys():返回键名的遍历器
    • values():返回键值的遍历器
    • entries():返回键值对的遍历器
    • forEach():使用回调函数遍历每个成员

    keys()、values()、entries()的使用

    let set = new Set(['red', 'green', 'blue']);
    
    for (let item of set.keys()) {
      console.log(item);
    }
    // red
    // green
    // blue
    
    for (let item of set.values()) {
      console.log(item);
    }
    // red
    // green
    // blue
    
    for (let item of set.entries()) {
      console.log(item);
    }
    // ["red", "red"]
    // ["green", "green"]
    // ["blue", "blue"]

    forEach的使用

    let set = new Set([1, 2, 3]);
    set.forEach((value, key) => console.log(value * 2) )
    // 2
    // 4
    // 6

    set与数组的转换

    数组转换成set结构只需要将数组加入到set构造函数参数中实例化即可

    set集合转换成数组,可简单的使用扩展运算符...,也可使用Array.from()的新方法

    var items = new Set([1, 2, 3, 4, 5]);
    var array1 = Array.from(items);
    
    var array2 = [...items]
    
    array1 // [1, 2, 3, 4, 5]
    array2 // [1, 2, 3, 4, 5]

    3. Map

    Map也是ES6中新引入的数据结构,它类似于Hash结构,属于键=>值对的结构,每一项值可用key=>value来表示

    通过实例化构造函数生成一个map对象,再通过.set方法设置相关项的键值对,通过.get方法获取相应的键值对

    var m = new Map();
    var obj = {str: 'str'};
    
    m.set(obj, 'content');
    m.get(obj) // "content"

    也可以直接在构造函数中加入一个数组参数,直接实例化出map对象

    var map = new Map([
      ['name', '张三'],
      ['title', 'Author']
    ]);
    
    map.size // 2
    map.has('name') // true
    map.get('name') // '张三''
    map.has('title') // true
    map.get('title') // 'Author'

    类似Set,Map也有一些常见的属性和方法

    • size属性 返回Map结构的成员总数。
    • set(key, value) 设置key所对应的键值,然后返回整个Map结构。如果key已经有值,则键值会被更新,否则就新生成该键
    • get(key) 读取key对应的键值,如果找不到key,返回undefined
    • has(key) 返回一个布尔值,表示某个键是否在Map数据结构中
    • delete(key) 删除某个键,返回true。如果删除失败,返回false
    • clear() 清除所有成员,没有返回值。

    类似Set,Map也有一些常见的遍历方法

    • keys():返回键名的遍历器。
    • values():返回键值的遍历器。
    • entries():返回所有成员的遍历器。
    • forEach():遍历Map的所有成员
    let map = new Map([
      ['F', 'no'],
      ['T',  'yes'],
    ]);
    
    for (let key of map.keys()) {
      console.log(key);
    }
    // "F"
    // "T"
    
    for (let value of map.values()) {
      console.log(value);
    }
    // "no"
    // "yes"
    
    for (let item of map.entries()) {
      console.log(item[0], item[1]);
    }
    // "F" "no"
    // "T" "yes"
    
    // 或者
    for (let [key, value] of map.entries()) {
      console.log(key, value);
    }
    
    // 等同于使用map.entries()
    for (let [key, value] of map) {
      console.log(key, value);
    }

    Map与数组的转换

    与Set一样,Map和数组直接也可以相互转换

    使用扩展运算符...可以将Map转换为数组

    let myMap = new Map().set(true, 7).set({foo: 3}, ['abc']);
    [...myMap]
    // [ [ true, 7 ], [ { foo: 3 }, [ 'abc' ] ] ]

    实例化Map构造函数时传入参数可将数组转换为Map对象

    new Map([[true, 7], [{foo: 3}, ['abc']]])
    // Map {true => 7, Object {foo: 3} => ['abc']}

    4. WeakSet

    ...

    5. WeakMap

    ...

    后记:

    ES6的内容实在是太多了,打算阅读相关新特性文档后做个笔记,蓦然发现经常会不耐烦

    文章不知从何写起,不知如何布局文章内容结构,写完之后又觉得不够全面或者理解还未到位,每每想不再继续

    写到这篇set和map,已经没啥耐心写下去了

    还是好好看看其他人的总结吧,全面许多

  • 相关阅读:
    Android-Sqlite-OOP方式操作增删改查
    Android-Sqlite-升级操作
    Android-Sqlite-SQL操作增删改查
    Android-SqliteSQL语句大全
    Android-startService后台运行
    php获取post参数的几种方式 RPC 规定接收取值方式 $GLOBALS['HTTP_RAW_POST_DATA'];
    php echo '<script>alert("插入成功")</script>';
    php urlencode函数 (中文字符转换为十六进制)
    Validform使用ajax详解
    PHP系统级函数 get_headers() 包含有服务器响应一个 HTTP
  • 原文地址:https://www.cnblogs.com/imwtr/p/5913790.html
Copyright © 2020-2023  润新知