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-阮一峰

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,219评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,363评论 1 293
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,933评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,020评论 0 206
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,400评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,640评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,896评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,597评论 0 199
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,327评论 1 244
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,581评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,072评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,399评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,054评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,083评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,849评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,672评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,585评论 2 270

推荐阅读更多精彩内容

  • 概述 ES5的对象属性名都是字符串,这容易造成属性名的冲突。比如,你使用了一个他人提供的对象,但又想为这个对象添加...
    oWSQo阅读 492评论 1 3
  • 国家电网公司企业标准(Q/GDW)- 面向对象的用电信息数据交换协议 - 报批稿:20170802 前言: 排版 ...
    庭说阅读 10,507评论 6 13
  • 1.概述 ES5的对象属性名都是字符串,这容易造成属性名的冲突。比如,你使用了一个他人提供的对象,但又想为这个对象...
    赵然228阅读 772评论 2 10
  • [TOC] 参考阮一峰的ECMAScript 6 入门参考深入浅出ES6 let和const let和const都...
    郭子web阅读 1,745评论 0 1
  • Deng等等阅读 131评论 0 0