zoukankan      html  css  js  c++  java
  • ES6必知必会 (四)—— Symbol、Set和Map

    Symbol

    1.Symbol 是 ES6 引入了一种新的原始数据类型,表示独一无二的值。它是 JavaScript 语言的第七种数据类型,前六种分别是:undefined、null、布尔值(Boolean)、字符串(String)、数值(Number)、对象(Object);

    2.Symbol 值通过Symbol函数生成,可以作为对象的属性名使用,保证不会与其他属性名产生冲突;

    let s = Symbol();
    typeof s  // symbol
    

    ps:上面代码表示创建一个Symbol变量,值得注意的是,Symbol函数前不能使用new命令,否则会报错,也就是说Symbol 是一个原始类型的值,不是对象,也不能添加属性;

    3.Symbol函数可以接受一个字符串作为参数,表示对 Symbol 实例的描述,主要用于区分不同的 Symbol 变量;

    let s1 = Symbol('a');
    let s2 = Symbol('b');
    
    s1.toString()  // 'Symbol(a)'
    s2.toString()  // 'Symbol(b)'
    

    ps:Symbol函数的参数只是表示对当前 Symbol 值的描述,因此相同参数的Symbol函数的返回值是不相等的

    let s1 = Symbol('a');
    let s2 = Symbol('a');
    
    s1 === s2  //false
    

    4.Symbol 值不能与其他类型的值进行运算,但可以转为布尔值,但是不能转为数值;

      let s = Symbol();
      s + '2'       // Cannot convert a Symbol value to a string
      Boolean(s)    // true
      !s            // false
    

    5.用于对象的属性名,可以保证不会出现同名的属性,对于一个对象由多个模块构成的情况非常有用,能防止某一个键被不小心改写或覆盖;值得注意的是,Symbol 值作为对象属性名时,不能用点运算符,因为点运算符后面是一个字符串;

    let s = Symbol();
    
    let obj = {};
    obj[s] = 'hello world';
    
    //或者
    
    let obj  = {
        [s] : 'hello world'
    }
    
    obj.s   // undefined
    obj[s]  // hello world
    

    6.Symbol 作为属性名,不会被常规方法遍历得到,即该属性不会出现在for...in、for...of循环中,也不会被Object.keys()、Object.getOwnPropertyNames()、JSON.stringify()返回,但是,它并不是私有属性,可以使用 Object.getOwnPropertySymbols 方法,可以获取指定对象的所有 Symbol 属性名;

    var obj = {};
    var a = Symbol('a');
    var b = Symbol('b');
    
    obj[a] = 'Hello';
    obj[b] = 'World';
    obj.c  = 'Mine';
    
    for( let key in obj ){
       console.log(key)         // c
    }
    
    var objectSymbols = Object.getOwnPropertySymbols(obj);
    
    console.log(objectSymbols) // [Symbol(a), Symbol(b)]
    

    7.Symbol.for方法接受一个字符串作为参数,然后搜索有没有以该参数作为名称的Symbol值。如果有,就返回这个Symbol值,否则就新建并返回一个以该字符串为名称的Symbol值;它与Symbol()不同的是,Symbol.for()不会每次调用就返回一个新的 Symbol 类型的值,而是会先检查给定的key是否已经存在,如果不存在才会新建一个值,而 Symbol()每次都会返回3不同的Symbol值;

    Symbol.for("name") === Symbol.for("name")
    // true
    
    Symbol("name") === Symbol("name")
    // false
    

    8.Symbol.keyFor方法返回一个已登记的 Symbol 类型值的key,而Symbol()写法是没有登记机制的;

    var s1 = Symbol.for("name");
    Symbol.keyFor(s1) // "name"
    
    var s2 = Symbol("name");
    Symbol.keyFor(s2) // undefined
    

    ps:Symbol.for为Symbol值登记的名字,是全局环境的,可以在不同的 iframe 或 service worker 中取到同一个值

    Set 和 Map

    1.ES6 提供了新的数据结构 Set。它类似于数组,但是成员的值都是唯一的,没有重复的值,它 本身是一个构造函数,用来生成 Set 数据结构。

    let s = new Set([1,2,3,4,5,2,2,3,5]);
    s // [1,2,3,4,5]
    

    2.可以使用add(key)方法可以添加元素到Set中,可以重复添加,但不会有效果,值得注意的是向Set加入值的时候,不会发生类型转换,即 5 和 "5" 是两个不同的值,但在 Set 内部,两个NaN是相等

    let s = new Set([1,2,3]);
    s.add(4)   //[1,2,3,4]
    s.add(4)   //[1,2,3,4]
    s.add(5)   //[1,2,3,4,5]
    s.add('5') //[1,2,3,4,5,"5"]
    s.add(NaN) //[1,2,3,4,5,"5",NaN]
    s.add(NaN) //[1,2,3,4,5,"5",NaN]
    

    3.可以利用Set数据不重复的特性,提供一种新的数组去重方法

    // 去除数组的重复成员
    [...new Set(array)]
    
    [...new Set([1,2,2,3,3,4,5,5])]  //[1,2,3,4,5]
    

    4.Set常见的操作方法有:

    • add(value):添加某个值,返回Set结构本身。

    • delete(value):删除某个值,返回一个布尔值,表示删除是否成功。

    • has(value):返回一个布尔值,表示该值是否为Set的成员。

    • clear():清除所有成员,没有返回值。
      <pre>
      s.add(1).add(2).add(2);
      // 注意2被加入了两次

      s.size // 2

      s.has(1) // true
      s.has(2) // true
      s.has(3) // false

      s.delete(2);
      s.has(2) // false
      </pre>

    5.Set 结构的实例有四个遍历方法,可以用于遍历成员。

    • keys():返回键名的遍历器

    • values():返回键值的遍历器

    • entries():返回键值对的遍历器

    • forEach():使用回调函数遍历每个成员
      需要特别指出的是,Set的遍历顺序就是插入顺序。这个特性有时非常有用,比如使用Set保存一个回调函数列表,调用时就能保证按照添加顺序调用。
      <pre>
      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"]
      </pre>

    6.ES6 提供了 Map 数据结构,它类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键,是一种更完善的 Hash 结构实现。如果你需要“键值对”的数据结构,Map 比 Object 更合适;

    7.Map常见的操作方法有:

    • set(key,val):添加某个值,返回Map结构本身。
    • get(key): 读取某个键,如果该键未知,则返回undefined
    • delete(key): 删除某个键,返回一个布尔值,表示删除是否成功。
    • has(key): 返回一个布尔值,表示该值是否为Map的键。
    • clear() : 清除所有成员,没有返回值。

    <pre>
    const m = new Map();
    const o = { str : 'Hello World'};

    m.set(o, 'content')
    m.get(o) // "content"
    
    m.has(o) // true
    m.delete(o) // true
    m.has(o) // false
    

    </pre>

    8.只有对同一个对象的引用,Map 结构才将其视为同一个键

    const map = new Map();
    
    const k1 = ['a'];
    const k2 = ['a'];
    
    map.set(k1, 111).set(k2, 222);
    
    map.get(k1) // 111
    map.get(k2) // 222
    

    上面例子表明,Map 的键实际上是跟内存地址绑定的,只要内存地址不一样,就视为两个键,因为 k1 和 k2 是两个不同的对象,放在不同的内存地址中,所以Map视为不同的键

    9.Map 结构原生提供三个遍历器生成函数和一个遍历方法。

    • keys():返回键名的遍历器。
    • values():返回键值的遍历器。
    • entries():返回所有成员的遍历器。
    • forEach():遍历 Map 的所有成员。

    ps:Map 的遍历顺序就是插入顺序,这里就不示例了,大家自己动手实践一下。

    10.可以使用扩展运算符(...)将Map转换为数组,反过来,将数组传入 Map 构造函数,就可以转为 Map了

    //Map转数组
    const map = new Map();
    map.set('name' , 'hello').set({},'world');
    
    [...map] //[["name","hello"],[{},"world"]]
    
    //数组转Map
    const map = new Map([["name","hello"],[{},"world"]]);
    
    map // {"name" => "hello", Object {} => "world"}




  • 相关阅读:
    Contest20140710 eagleeggs
    bzoj 1059: [ZJOI2007]矩阵游戏 二分图匹配
    Quick-Cocos2d-x初学者游戏教程(二) -------------------- Quick内部的代码结构及相应的原理
    Quick-Cocos2d-x初学者游戏教程(一)--------------------Quick的一些基础知识
    使用Cocos Studio 1.6 编辑人物属性界面
    Cocos2d-x 3.0 开发(十四)使用UIScrollView 实现大小不同物品拖动展示
    使用Cocos Studio 1.6 编辑开始界面
    Cocos2d-x Json用法
    Cocos2d-x xml解析
    plist文件操作
  • 原文地址:https://www.cnblogs.com/wntd/p/9013283.html
Copyright © 2011-2022 走看看