ES6 语法糖

语法糖(Syntactic sugar)

语法糖(Syntactic sugar),也译为糖衣语法,是由英国计算机科学家彼得·约翰·兰达(Peter J. Landin)发明的一个术语,指计算机语言中添加的某种语法,这种语法对语言的功能并没有影响,但是更方便程序员使用。通常来说使用语法糖能够增加程序的可读性,从而减少程序代码出错的机会。

Symbol

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

Symbol值通过Symbol函数生成。这就是说,对象的属性名现在可以有两种类型,一种是原来就有的字符串,另一种就是新增的Symbol类型。凡是属性名属于Symbol类型,就都是独一无二的,可以保证不会与其他属性名产生冲突。

    let s = Symbol();
    typeof s
    // "symbol
    s;
    //Symbol();
复制代码

每个Symbol都是独一无二的

    let a = Symbol('bar');//Symbol(bar)
    let b = Symbol('bar');
    b.toString(); //"Symbol(bar)"
    a==b //false
    a.toString()==b.toString() //true
复制代码

!!Symbol不是对象,不能用new,也就不能添加属性。

Symbol的使用
  1. 作为属性名(注意,Symbol值作为对象属性名时,不能用点运算符。)
    var mySymbol = Symbol();
    // 第一种写法
    var a = {};
    a[mySymbol] = 'Hello!';
    // 第二种写法
    var a = {
      [mySymbol]: 'Hello!'
    };
    // 第三种写法
    var a = {};
    Object.defineProperty(a, mySymbol, { value: 'Hello!' });
    // 以上写法都得到同样结果
    a[mySymbol] // "Hello!"
复制代码
  1. 消除魔术字符串

魔术字符串指的是,在代码之中多次出现、与代码形成强耦合的某一个具体的字符串或者数值。风格良好的代码,应该尽量消除魔术字符串,该由含义清晰的变量代替。

    <!--例如-->
    function getArea(shape, options) {
      var area = 0;
    
      switch (shape) {
        case 'Triangle': // 魔术字符串
          area = .5 * options.width * options.height;
          break;
        /* ... more code ... */
      }
    
      return area;
    }
    
    getArea('Triangle', { width: 100, height: 100 }); // 魔术字符串
复制代码

上面代码中,字符串“Triangle”就是一个魔术字符串。它多次出现,与代码形成“强耦合”,不利于将来的修改和维护。常用的消除魔术字符串的方法,就是把它写成一个变量。

    <!--例如-->
    var shapeType = {
      triangle: 'Triangle'
    };
    
    function getArea(shape, options) {
      var area = 0;
    
      switch (shape) {
        case shapeType.triangle: // 魔术字符串
          area = .5 * options.width * options.height;
          break;
        /* ... more code ... */
      }
    
      return area;
    }
    
    getArea(shapeType.triangle, { width: 100, height: 100 }); // 魔术字符串
复制代码

上面代码中,我们把“Triangle”写成shapeType对象的triangle属性,这样就消除了强耦合。

如果仔细分析,可以发现shapeType.triangle等于哪个值并不重要,只要确保不会跟其他shapeType属性的值冲突即可。因此,这里就很适合改用Symbol值。

    const shapeType = {
      triangle: Symbol()
    };
复制代码
  1. 特殊功能

由于以 Symbol 值作为名称的属性,不会被常规方法遍历得到。我们可以利用这个特性,为对象定义一些非私有的、但又希望只用于内部的方法。

    let s = Symbol('my_key');
    let obj = {
      [s]: 1,
      enum: 2,
      nonEnum: 3
    };
    for(let item in obj){
        console.log(item);
    }
    // enum,nonEnum
    obj[s]; //1
    Reflect.ownKeys(obj)
    // [Symbol(my_key), 'enum', 'nonEnum']
复制代码
  1. Symbol.for(),Symbol.keyFor()
    var s1 = Symbol.for('foo');
    var s2 = Symbol.for('foo');
    s1 === s2 // true
    
    var s1 = Symbol.for("foo");
    Symbol.keyFor(s1) // "foo"
    var s2 = Symbol("foo");
    Symbol.keyFor(s2) // undefined
复制代码
  1. 模块的 Singleton 模式
    // mod.js
    const FOO_KEY = Symbol.for('foo');
    
    function A() {
      this.foo = 'hello';
    }
    
    if (!global[FOO_KEY]) {
      global[FOO_KEY] = new A();
    }
    
    module.exports = global[FOO_KEY];
    //上面代码中,可以保证global[FOO_KEY]不会被无意间覆盖,但还是可以被改写。
    var a = require('./mod.js'); 
    global[Symbol.for('foo')] = 123;
    //键名使用Symbol方法生成,那么外部将无法引用这个值,当然也就无法改写
    const FOO_KEY = Symbol('foo');
复制代码
  1. 内置的Symbol值

    Symbol.hasInstance。 对象的Symbol.hasInstance属性,指向一个内部方法。当其他对象使用instanceof运算符,判断是否为该对象的实例时,会调用这个方法。比如,foo instanceof Foo在语言内部,实际调用的是Foo[Symbol.hasInstance](f oo)。

    class MyClass {
      [Symbol.hasInstance](foo) {
        return foo instanceof Array;
      }
    }
    
    [1, 2, 3] instanceof new MyClass() // true
    
    class Even {
      static [Symbol.hasInstance](obj) {
        return Number(obj) % 2 === 0;
      }
    }
    
    1 instanceof Even // false
    2 instanceof Even // true
    12345 instanceof Even // false
复制代码
Symbol.isConcatSpreadable
对象的Symbol.isConcatSpreadable属性等于一个布尔值,表示该对象使用Array.prototype.concat()时,是否可以展开。
复制代码
    let arr1 = ['c', 'd'];
    ['a', 'b'].concat(arr1, 'e') // ['a', 'b', 'c', 'd', 'e']
    arr1[Symbol.isConcatSpreadable] // undefined
    
    let arr2 = ['c', 'd'];
    arr2[Symbol.isConcatSpreadable] = false;
    ['a', 'b'].concat(arr2, 'e') // ['a', 'b', ['c','d'], 'e']
复制代码
类似数组的对象也可以展开,但它的Symbol.isConcatSpreadable属性默认为false,必须手动打开。
复制代码

set和map数据结构

数据结构set
ES6提供了新的数据结构Set。它类似于数组,但是成员的值都是唯一的,没有重复的值。
Set本身是一个构造函数,用来生成Set数据结构。
复制代码
    var s = new Set();
    
    [2, 3, 5, 4, 5, 2, 2].map(x => s.add(x));
    
    for (let i of s) {
      console.log(i);
    }
    // 2 3 5 4
    [...s]//[2,3,5,4]
    //
    s.size //4
复制代码
  • add(value):添加某个值,返回Set结构本身。
  • delete(value):删除某个值,返回一个布尔值,表示删除是否成功。
  • has(value):返回一个布尔值,表示该值是否为Set的成员。
  • clear():清除所有成员,没有返回值。
  • Array.from(new Set([1,2,3,4])):转成数组。
  • keys():返回键名的遍历器
  • values():返回键值的遍历器
  • entries():返回键值对的遍历器
  • forEach():使用回调函数遍历每个成员
    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"]
复制代码
WeakSet

WeakSet结构与Set类似,也是不重复的值的集合。但是,它与Set有两个区别。

首先,WeakSet的成员只能是对象,而不能是其他类型的值。

其次,WeakSet中的对象都是弱引用,即垃圾回收机制不考虑WeakSet对该对象的引用,也就是说,如果其他对象都不再引用该对象,那么垃圾回收机制会自动回收该对象所占用的内存,不考虑该对象还存在于WeakSet之中。这个特点意味着,无法引用WeakSet的成员,因此WeakSet是不可遍历的。

    var a = [[1,2], [3,4]];
    var ws = new WeakSet(a);
复制代码
Map

JavaScript的对象(Object),本质上是键值对的集合(Hash结构),但是传统上只能用字符串当作键。这给它的使用带来了很大的限制。

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

    var m = new Map([
      [true, 'foo'],
      ['true', 'bar']
    ]);
    
    m.get(true) // 'foo'
    m.get('true') // 'bar'
复制代码
  • size属性:m.size
  • set(key, value):m.set("hello","vv")
  • get(key)
  • has(key)
  • delete(key)
  • clear()
  • keys():返回键名的遍历器。
  • values():返回键值的遍历器。
  • entries():返回所有成员的遍历器。
  • forEach():遍历Map的所有成员。

转载于:https://juejin.im/post/5cd50eff6fb9a032076c2341

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值