ES6之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.prototype.description

直接返回Symbol的描述

const sym = Symbol('foo');

sym.description // "foo"

三、作为属性名的Symbol

作为属性名的Symbol对象不会出现同名属性

let mySymbol = Symbol();

// 第一种写法
let a = {};
a[mySymbol] = 'Hello!';

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

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

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

注意:Symbol 值作为对象属性名时,不能用点运算符,必须放在方括号([])之中

let s = Symbol();

let obj = {
  [s]: function (arg) { ... }
};

obj[s](123);

四、属性名的遍历

Symbol 作为属性名,遍历对象的时候,该属性不会出现在for...infor...of循环中,也不会被Object.keys()Object.getOwnPropertyNames()JSON.stringify()返回,使用Object.getOwnPropertySymbols()方法可以获取Symbol属性名

const obj = {};
let a = Symbol('a');
let b = Symbol('b');

obj[a] = 'Hello';
obj[b] = 'World';

const objectSymbols = Object.getOwnPropertySymbols(obj);

objectSymbols
// [Symbol(a), Symbol(b)]

使用 Reflect.ownKeys()方法可以返回所有类型的键名

五、Symbol.for(),Symbol.keyFor()

  • Symbol.for()
    该方法接受一个参数,搜索参数对应的Symbol值,存在则返回并注册至全局,不存在则新建一个以该参数为名称的Symbol值,并注册至全局
Symbol.for("bar") === Symbol.for("bar")
// true

Symbol("bar") === Symbol("bar")
// false
  • Symbol.keyFor()
    返回一个已登记的 Symbol 类型值的描述(key)
let s1 = Symbol.for("foo");
Symbol.keyFor(s1) // "foo"

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

六、内置的Symbol值

1.Symbol.hasInstance
当其他对象使用instanceof运算符,判断是否为该对象的实例时,会调用这个方法。

const Even = {
  [Symbol.hasInstance](obj) {
    return Number(obj) % 2 === 0;
  }
};

1 instanceof Even // false
2 instanceof Even // true
12345 instanceof Even // false

2.Symbol.isConcatSpreadable
该属性等于一个布尔值,表示该对象用于Array.prototype.concat()时,是否可以展开

let arr2 = ['c', 'd'];
arr2[Symbol.isConcatSpreadable] = false;
['a', 'b'].concat(arr2, 'e') // ['a', 'b', ['c','d'], 'e']

3.Symbol.species
创建衍生对象时,会使用该属性,定义Symbol.species属性要采用get取值器

class MyArray extends Array {
  static get [Symbol.species]() { return Array; }
}

const a = new MyArray();
const b = a.map(x => x);

b instanceof MyArray // false
b instanceof Array // true

4.Symbol.match、Symbol.replace、Symbol.search、Symbol.split

  • 对象的Symbol.match属性,指向一个函数,执行str.match时会调用它
  • 对象的Symbol.replace属性,指向一个函数,执行String.prototype.replace时会调用它
  • 对象的Symbol.search属性,指向一个函数,执行String.prototype.search时会调用它
  • 对象的Symbol.split属性,指向一个函数,执行String.prototype.split时会调用它
String.prototype.match(regexp)
// 等同于
regexp[Symbol.match](this)

class MyMatcher {
  [Symbol.match](string) {
    return 'hello world'.indexOf(string);
  }
}

'e'.match(new MyMatcher()) // 1

5.Symbol.iterator
该属性指向该对象的默认遍历器方法

const myIterable = {};
myIterable[Symbol.iterator] = function* () {
  yield 1;
  yield 2;
  yield 3;
};

[...myIterable] // [1, 2, 3]

6.Symbol.toPrimitive
对象被转为原始类型的值时,会调用这个方法,该方法接受一个字符串参数,返回该对象对应的原始类型值

let obj = {
  [Symbol.toPrimitive](hint) {
    switch (hint) {
      case 'number':
        return 123;
      case 'string':
        return 'str';
      case 'default':
        return 'default';
      default:
        throw new Error();
     }
   }
};

2 * obj // 246
3 + obj // '3default'
obj == 'default' // true
String(obj) // 'str'

7.Symbol.toStringTag
这个属性可以用来定制[object Object][object Array]object后面的那个字符串

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

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

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Symbol(符号) 一. 概念 注:Symbol为生产Symbol类型数据的函数,而不是数据类型本身 值类型而非...
    LOVE小狼阅读 3,411评论 0 0
  • 1、为什么添加Symbol基本类型 虽然学习ES6一段时间了,但是由于工作中没有使用到,对Symbol数据类型一直...
    xinranlin阅读 2,953评论 0 0
  • 9 Symbol #9.1 介绍 ES6引入Symbol作为一种新的原始数据类型,表示独一无二的值,主要是为了防止...
    Daeeman阅读 1,540评论 0 1
  • 概述 ES5的对象属性名都是字符串,这容易造成属性名的冲突。比如,你使用了一个他人提供的对象,但又想为这个对象添加...
    oWSQo阅读 3,505评论 1 3
  • 16宿命:用概率思维提高你的胜算 以前的我是风险厌恶者,不喜欢去冒险,但是人生放弃了冒险,也就放弃了无数的可能。 ...
    yichen大刀阅读 11,277评论 0 4