ES6

头像
梁柱
    阅读 5 分钟
    1

    Symbol

    ES6 引入了一种新的原始数据类型 Symbol,表示独一无二的值。

    基本用法

    1.Symbol 函数栈不能用 new 命令,因为 Symbol 是原始数据类型,不是对象。

    //使用 typeof,结果为 "symbol"
    let s = Symbol();
    console.log(typeof s);//symbol
    
    //instanceof 的结果为 false
    let s1 = Symbol("foo");
    console.log(s1 instanceof Symbol);//false

    2.可以接受一个字符串作为参数,为新创建的 Symbol 提供描述,用来显示在控制台或者作为字符串的时候使用,便于区分。

    //可以接受一个字符串作为参数,表示对 Symbol 实例的描述
    let s2 = Symbol('foo');
    console.log(s1); // Symbol(foo)

    3.如果 Symbol 的参数是一个对象,就会调用该对象的 toString 方法,将其转为字符串,然后才生成一个 Symbol 值。

    // Symbol 的参数是一个对象
    const obj = {
      toString() {
        return 'abc';
      }
    };
    const sym = Symbol(obj);
    console.log(sym); // Symbol(abc)

    4.Symbol 函数的参数只是表示对当前 Symbol 值的描述,相同参数的 Symbol 函数的返回值是不相等的。

    // 没有参数的情况
    let s1 = Symbol();
    let s2 = Symbol();
    
    console.log(s1 === s2); // false
    
    // 有参数的情况
    let s1 = Symbol('foo');
    let s2 = Symbol('foo');
    
    console.log(s1 === s2); // false

    使用场景

    作为属性名

    由于每一个 Symbol 的值都是不相等的,所以 Symbol 作为对象的属性名,可以保证属性不重名。

    let mySymbol = Symbol();
    //写法一
    let a = {};
    a[mySymbol] = "Hello";
    
    //写法二
    let a = {
      [mySymbol]: "Hello",
    };
    
    //写法三
    let a = {};
    Object.defineProperty(a, mySymbol, {value: "Hello"});
    
    console.log(a[mySymbol]); //Hello

    Symbol 作为对象属性名时不能用.运算符,要用方括号。因为.运算符后面是字符串,所以取到的是字符串 mySymbol 属性,而不是 Symbol 值 mySymbol 属性。

    注意: Symbol 作为属性名,该属性不会出现在 for...infor...of 循环中,也不会被 Object.keys()Object.getOwnPropertyNames()JSON.stringify() 返回。但是,它也不是私有属性,有一个 Object.getOwnPropertySymbols 方法,可以获取指定对象的所有 Symbol 属性名。

    定义常量

    使用 Symbol 定义常量,这样就可以保证这一组常量的值都不相等。

    const COLOR_RED = Symbol("red");
    const COLOR_YELLOW = Symbol("yellow");
    const COLOR_BLUE = Symbol("blue");
    Symbol.for() 和 Symbol.keyFor()

    如果我们希望使用同一个 Symbol 值,可以使用 Symbol.for。它接受一个字符串作为参数,然后搜索有没有以该参数作为名称的 Symbol 值。如果有,就返回这个 Symbol 值,否则就新建并返回一个以该字符串为名称的 Symbol 值。

    let s1 = Symbol.for("foo");
    let s2 = Symbol.for("foo");
    console.log(s1); //Symbol(foo)
    console.log(s2); //Symbol(foo)
    console.log(s1 === s2); //true

    Symbol.keyFor 方法返回一个已登记的 Symbol 类型值的 key。

    let s1 = Symbol.for("foo");
    let s2 = Symbol.for("foo");
    console.log(Symbol.keyFor(s1)); //foo
    console.log(Symbol.keyFor(s2));//foo

    set

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

    初始化

    Set 本身是一个构造函数,用来生成 Set 数据结构。
    Set 函数可以接受一个数组(或者具有 iterable 接口的其他数据结构)作为参数,用来初始化。

    let set = new Set([1, 2, 3, 4]);
    console.log(set);
    
    set = new Set(document.querySelectorAll('div'));
    console.log(set.size); // 66
    
    set = new Set(new Set([1, 2, 3, 4]));
    console.log(set.size); // 4

    属性和方法

    属性 描述
    Set.prototype.constructor 构造函数,默认就是 Set 函数。
    Set.prototype.size 返回 Set 实例的成员总数。
    操作方法 描述
    add(value) 添加某个值,返回 Set 结构本身。
    delete(value) 删除某个值,返回一个布尔值,表示删除是否成功。
    has(value) 返回一个布尔值,表示该值是否为 Set 的成员。
    clear() 清除所有成员,无返回值。
    let set = new Set();
    console.log(set.add(1).add(2)); // Set { 1, 2 }
    
    console.log(set.delete(2)); // true
    console.log(set.has(2)); // false
    console.log(set); // Set { 1 }
    
    console.log(set.clear()); // undefined
    console.log(set.has(1)); // false
    console.log(set); // Set {}
    遍历方法 描述
    keys() 返回键名的遍历器
    values() 返回键值的遍历器
    entries() 返回键值对的遍历器
    forEach() 使用回调函数遍历每个成员,无返回值
    注意 keys()、values()、entries() 返回的是遍历器
    let set = new Set(["a", "b", "c"]);
    console.log(set.keys());//[Set Iterator] { 'a', 'b', 'c' }
    console.log([...set.keys()]);//[ 'a', 'b', 'c' ]
    
    console.log(set.values()); //[Set Iterator] { 'a', 'b', 'c' }
    console.log([...set.values()]); //[ 'a', 'b', 'c' ]
    
    console.log(set.entries());//[Set Entries] { [ 'a', 'a' ], [ 'b', 'b' ], [ 'c', 'c' ] }
    console.log([...set.entries()]);//[ [ 'a', 'a' ], [ 'b', 'b' ], [ 'c', 'c' ] ]
    
    set.forEach((value, key) => {
      console.log(key + " " + value);
    });
    // a a
    // b b
    // c c

    Set 对象作用

    数组去重
    let mySet = new Set([1, 2, 3, 4]);
    console.log([...mySet]);//[ 1, 2, 3, 4 ]
    并集
    let set1 = new Set([1, 2, 3]);
    let set2 = new Set([2, 3, 4]);
    let union = new Set([...set1, ...set2]);
    console.log(union); //Set { 1, 2, 3, 4 }
    交集
    let set1 = new Set([1, 2, 3]);
    let set2 = new Set([2, 3, 4]);
    let intersect = new Set([...set1].filter(x => set2.has(x)));
    console.log(intersect);//Set { 2, 3 }
    差集
    let set1 = new Set([1, 2, 3]);
    let set2 = new Set([2, 3, 4]);
    let intersect = new Set([...set1].filter(x => !set2.has(x)));
    console.log(intersect);//Set { 1 }

    WeakSet

    1.只接受对象作为键名
    2.只有add()、delete()、clear()、has()三个方法,不能遍历,没有size属性等
    3.WeakMap 的键名所引用的对象是弱引用

    即垃圾回收机制不将该引用考虑在内。只要所引用的对象的其他引用都被清除,垃圾回收机制就会释放该对象所占用的内存。也就是说,一旦不再需要,WeakMap 里面的键名对象和所对应的键值对会自动消失,不用手动删除引用。

    4.WeakSet主要用来储存DOM节点,当这些节点从文档移除时,不会引发内存泄漏。

    Map

    Map 对象保存键值对。任何值(对象或者原始值) 都可以作为一个键或一个值。
    Map 和 Object 的区别
    一个Object的键只能是字符串或者Symbol,但一个Map的键可以是任意值。
    Map中的键值是有序的(FIFO 原则),而添加到对象中的键则不是。
    Map 的键值对个数可以从 size 属性获取,而 Object 的键值对个数只能手动计算。
    Object 都有自己的原型,原型链上的键名有可能和你自己在对象上的设置的键名产生冲突。

    Map中的key

    key 是 NaN

    虽然 NaN 和任何值甚至和自己都不相等(NaN !== NaN 返回true),NaN作为Map的键来说是没有区别的。
    let myMap = new Map();
    myMap.set(NaN, "not a number");
    console.log(myMap.get(NaN)); //not a number
    
    let otherNaN = Number("foo");
    console.log(myMap.get(otherNaN)); //not a number

    Map的迭代

    对 Map 进行遍历,有如下两个方法:

    for...of
    forEach()

    Map对象的操作

    Map 与 Array的转换

    let kvArray = [["key1", "value1"], ["key2", "value2"]];
    
    // Map 构造函数可以将一个 二维 键值对数组转换成一个 Map 对象
    let myMap = new Map(kvArray);
    console.log(myMap);//Map { 'key1' => 'value1', 'key2' => 'value2' }
    
    // 使用 Array.from 函数可以将一个 Map 对象转换成一个二维键值对数组
    let outArray = Array.from(myMap);
    console.log(outArray); //[ [ 'key1', 'value1' ], [ 'key2', 'value2' ] ]

    WeakMap

    1. WeakMap 只接受对象作为键名
    2. WeakMap 的键名所引用的对象是弱引用
    3. WeakMap 不像 Map,一是没有遍历操作(即没有keys()、values()和entries()方法),也没有 size 属性,也不支持 clear 方法,所以 WeakMap只有四个方法可用:get()、set()、has()、delete()。

    梁柱
    135 声望12 粉丝