es6-Symbol数据类型

Symbol

Symbol 是一个符号对象,是es6新添加的数据类型,通过Symbol()可以得到一个唯一的值,所以这个值很适合做标识符用。

1. 概述

Symbol的唯一性

Symbol值通过Symbol()函数生成,每个Symbol值是独一无二的。如

let s = Symbol();
let m = Symbol();
 console.log(m==s);//false

Symbol函数的参数

Symbol函数可以接受一个字符串作为参数,表示Symbol实例的描述,这个参数的目的是区分不同的Symbol
如:

let s1 = Symbol('foo');
let s2 = Symbol('bar');

s1 // Symbol(foo)
s2 // Symbol(bar)

s1.toString() // "Symbol(foo)"
s2.toString() // "Symbol(bar)"

如果上面两个Symbol值不加参数的话,那么输出的都是Symbol() 这样就难以区分了,但加上参数后就相当于为他们取了名字,这样就可以分开了。
注意:

  1. 即使你设置的参数是一样的,两个不同地点Symbol也是不同的,这就好比我们经常有人撞名字,同名同姓,但他们是不同的人。每个Symbol值就和人一样,都是独一无二的。
  2. 如果你的参数是一个对象,那么会自动调用对象的tostring()方法,返回的值则作为描述这个Symbol值的参数
const obj = {
  toString() {
    return 'abc';
  }
};
const sym = Symbol(obj);
sym // Symbol(abc)
  1. Symbol() function 返回一个类型为symbol的值,Symbol有静态属性,原型上也有methods,但是缺少constructor,所以你不能new Symbol()来执行;(简单来说是因为Symbol()函数生成的是Symbol数据类型的值,而不是对象,所以不能用new

Symbol值的运算和转化

  1. Symbol值不能与其他类型的值进行运行,否则会报错。

        let sym = Symbol('My symbol');
    
    "your symbol is " + sym
    // TypeError: can't convert symbol to string
    `your symbol is ${sym}`
    // TypeError: can't convert symbol to string
    
  2. Symbol可以转为字符串类、布尔值,但不可以转为数值。

    let sym = Symbol('My symbol');
    
    String(sym) // 'Symbol(My symbol)'
    sym.toString() // 'Symbol(My symbol)'
    
            let sym = Symbol();
        Boolean(sym) // true
        !sym  // false
        
        if (sym) {
          // ...
        }
        
        Number(sym) // TypeError
        sym + 2 // TypeError
    

作为属性名的Symbol

由于Symbo值是独一无二的,所以它特别适合做标识符,从而用来做对象的属性名,这样可以·防止同名属性的出现。

Symbol作为对象属性名

写法

let mySymbol = Symbol();
\\ 第一种写法
a[mySymbol] = 'Hello!';

\\第二种写法
let a = {
  [mySymbol] : 'Hello!'
};

\\ 第三种写法
let a = {};
Object.defineProperty(a, mySymbol, { value: 'Hello!'});

\\ 以上写法都得到同样结果
a[mySymbol] \\ "Hello"

注意:

  1. 这个时候,Symbol值作为对象名时,不能用点运算符。这是因为点运算符后面的部分都当成了字符串,而不是一个Symbol,所以,要调用Symbol值时,一定要用方括号。
  2. Symbol值也常用作常量,这时可以起到消除魔术字符串的作用

Symbol值的遍历方法

Symbol作为对象属性名的时候,不能用for...in for...of等方法遍历,要用它设定的方法

object.getOwnPropertySymbols方法

作用:可以返回指定对象的所有Symbol属性名
返回值:一个数组,成员是当前对象的所有用作属性名的Symbol值
例子:

    const obj = {};
    
    let foo = Symbol("foo");
    
    Object.defineProperty(obj, foo, {
      value: "foobar",
    });
    
    for (let i in obj) {
      console.log(i); // 无输出
    }
    
    Object.getOwnPropertyNames(obj)
    // []
    
    Object.getOwnPropertySymbols(obj)
    // [Symbol(foo)]

Reflect.ownKeys方法

作用:返回所有类型的键名,包括常规键名和Symbol键名
用法:可以用在创建一些非私有的内部方法。

Symbol.for(),Symbol.keyFor()

Symbol.for()

参数:接受一个字符串当参数
作用:把Symbol值登记在全局环境中供搜索,当有相同参数的Symbol值存在时,则会返回这个Symbol值的调用,没有的话,就会创建一个新的以给定参数的Symbol值。

    let s1 = Symbol.for('foo');
    let s2 = Symbol.for('foo');
    
    s1 === s2 // true

与Symbol()的区别:Symbol.for()会寻找之前的,而Symbol()一直创建新的Symbol值,如调用Symbol.for("cat")30 次,每次都会返回同一个 Symbol 值,但是调用Symbol("cat")30 次,会返回 30 个不同的 Symbol 值。

Symbol.keyFor()方法

作用:方法返回一个已登记的Symbol类型值的Key
例子

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

let s2 = Symbol("foo");
Symbol.keyFor(s2) // undefined

内置的Symbol值

Symbol.hasInstance

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

Symbol.isConcatSpreadable

对象的Symbol.isConcatSpreadable属性等于一个布尔值,表示该对象用于Array.prototype.concat()时,是否可以展开。
数组中:Symbol.isConcatSpreadable为true/undefined表示可以展开,false时则不能。

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']

类似数组的对象中,则默认不可以展开,必须要设置为true

Symbol.species

对象的Symbol.species属性,指向一个构造函数。创建衍生对象时,会使用该属性。
主要用途:有些类库是在基类的基础上修改的,那么子类使用继承的方法时,作者可能希望返回基类的实例,而不是子类的实例

Symbol.match

作用:对象的Symbol.match属性,指向一个函数。当执行str.match(myObject)时,如果该属性存在,会调用它,返回该方法的返回值。

Symbol.replace

作用:对象的Symbol.replace属性,指向一个方法,当该对象被String.prototype.replace方法调用时,会返回该方法的返回值。
参数:第一个参数是replace方法正在作用的对象,第二个参数是替换后的值。

Symbol.search

对象的Symbol.search属性,指向一个方法,当该对象被String.prototype.search方法调用时,会返回该方法的返回值。

Symbol.split

对象的Symbol.split属性,指向一个方法,当该对象被String.prototype.split方法调用时,会返回该方法的返回值。

Symbol.iterator

对象的Symbol.iterator属性,指向该对象的默认遍历器方法。对象进行for...of循环时,会调用Symbol.iterator方法,返回该对象的默认遍历器。

Symbol.toPrimitive

对象的Symbol.toPrimitive属性,指向一个方法。该对象被转为原始类型的值时,会调用这个方法,返回该对象对应的原始类型值。
参数:

  • Number:该场合需要转成数值
  • String:该场合需要转成字符串
  • Default:该场合可以转成数值,也可以转成字符串

Symbol.toStringTag

对象的Symbol.toStringTag属性,指向一个方法。在该对象上面调用Object.prototype.toString方法时,如果这个属性存在,它的返回值会出现在toString方法返回的字符串之中,表示对象的类型。也就是说,这个属性可以用来定制[object Object]或[object Array]中object后面的那个字符串。
例子:

// 例一
({[Symbol.toStringTag]: 'Foo'}.toString())
// "[object Foo]"

// 例二
class Collection {
  get [Symbol.toStringTag]() {
    return 'xxx';
  }
}
let x = new Collection();
Object.prototype.toString.call(x) // "[object xxx]"

Symbol.unscopables

对象的Symbol.unscopables属性,指向一个对象。该对象指定了使用with关键字时,哪些属性会被with环境排除。
参考-es6-阮一峰

你可能感兴趣的:(es6-Symbol数据类型)