ES6学习笔记:Symbol

21 篇文章 2 订阅
9 篇文章 1 订阅

Symbol

什么是Symbol

​ ES6引入了一种新的原始型数据类型 Symbol ,表示独一无二的值。它是JacaScript的第七中数据类型(现在JavaScript的数据类型:String、Number、Boolean、undefined、null、Symbol、Object)。

为什么要引入Symbol

​ ES6前所有对象的属性名都是字符串,如果你使用了别人的一个对象,又想为这个对象添加方法时,新方法的方法名就可能和原有方法的名字冲突。ES6中的Symbol值表示独一无二的值,如果属性名使用Symbol值就从根本上杜绝了这种冲突。

创建一个Symbol值

let sym = Symbol();
typeof(sym);  //Symbol

注意:创建Symbol值不能使用 new 命令,Symbol是一个原始型类型的值,不是对象。

Symbol函数可以接受一个字符串作为参数,表示对Symbol实例的描述,主要是为了在控制台显示,或者都转为字符串时,比较容易区分。

let sym1 = Symbol('sym1')
let sym2 = Symbol('sym2')
sym1.toString() // "Symbol(sym1)"
sym2.toString() // "Symbol(sym2)"

如果Symbol的参数是一个对象,就会立即调用对象的toString方法,将它专为字符串,然后在生成Symbol值。

注意:

  1. Symbol函数的参数只是表示对当前Symbol值的描述,因此相同参数的Symbol函数的返回值是不相等的
  2. Symbol值不能与其他类型的值进行运算
  3. Symbol 值可以显式转为字符串和布尔值,但是不能转换为数值

Symbol.prototype.description

为了能够方便的读取Symbol的描述添加了一个实例方法Symbol.prototype.dedcription

let sym = Symbol(sym1);
sym.description  //sym1

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 mySymbol = Symbol("HiSymbol");
let mySymbolFun = Symbol("HiSymbolFun");
let a = {};

a.string1 = 'string1!';
a['string2'] = 'string2!' 
// a: {string1: "string1!", string2: "string2!"}
//以上两种写法是字符串作为属性名给对象添加属性时的两种写法

a[mySymbol] = "myFirstSymbol" 
// a: {string1: "string1!", string2: "string2!", Symbol(HiSymbol): "myFirstSymbol"}
//加中括号,此为Symbol类型作为属性名赋值和取值时的正确写法
//同理在对象内部使用Symbol定义属性、对象调用方法时,也都要放在中括号中,不能使用.操作

let obj = {
    [mySymbol]:"Hello Symbol !",
    [mySymbolFun]:function(){
        console.log(this[mySymbol])
    },
};
obj[mySymbolFun]();
// Hello Symbol !

注意:

  1. 使用Symbol类型时要避免使用.操作符,基本上都要使用[ ]
  2. Symbol 值作为属性名时,该属性还是公开属性,不是私有属性。

Symbol作为属性名被遍历的时候不会出出现在for...infor...of循环中也不会被Obgect.keys()Object.getOwnPropertyNames()JSON.stringify()返回。

但是,它也不是私有属性,有一个Object.getOwnPropertySymbols()方法,可以获取指定对象的所有 Symbol 属性名。该方法返回一个数组,成员是当前对象的所有用作属性名的 Symbol 值。

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

obj[a] = 'Hello';
obj[b] = 'World';
obj['c'] = 'ccHello';
obj.d = 'ddWorld';

for (let i in obj) {
  console.log(i); 
}
// c
// d
console.log(obj); 
// {c: "ccHello", d: "ddWorld", Symbol(a): "Hello", Symbol(b): "World"}

Object.getOwnPropertySymbols(obj);
// [Symbol(a), Symbol(b)]

Symbol.for(),Symbol.keyFor()

有时,我们希望重新使用同一个 Symbol 值,Symbol.for()方法可以做到这一点。它接受一个字符串作为参数,然后搜索有没有以该参数作为名称的 Symbol 值。如果有,就返回这个 Symbol 值,否则就新建一个以该字符串为名称的 Symbol 值,并将其注册到全局。

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

s1 === s2 // true

上面代码中,s1s2都是 Symbol 值,但是它们都是由同样参数的Symbol.for方法生成的,所以实际上是同一个值。

Symbol.for()Symbol()这两种写法,都会生成新的 Symbol。它们的区别是,前者会被登记在全局环境中供搜索,后者不会。Symbol.for()不会每次调用就返回一个新的 Symbol 类型的值,而是会先检查给定的key是否已经存在,如果不存在才会新建一个值。比如,如果你调用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.for()为 Symbol 值登记的名字,是全局环境的,不管有没有在全局环境运行。

内置的 Symbol 值

除了定义自己使用的 Symbol 值以外,ES6 还提供了 11 个内置的 Symbol 值,指向语言内部使用的方法。

Symbol.hasInstance

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

Symbol.isConcatSpreadable

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

Symbol.species

对象的Symbol.species属性,指向一个构造函数。创建衍生对象时,会使用该属性。

Symbol.match

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

Symbol.replace

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

Symbol.search

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

Symbol.split

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

Symbol.iterator

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

Symbol.toPrimitive

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

Symbol.toStringTag

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

Symbol.unscopables

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

具体使用方法请看下方链接

《ECMAScript 6 入门教程》- 阮一峰

ES6入门-阮一峰 Symbol章节学习笔记总结

  • 5
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值