ES6学习笔记14:Symbol

基本定义

数据类型Symbol表示独一无二的值,是JavaScript中第七种数据类型。

JavaScript基本数据类型
  • undefined
  • null
  • 布尔值(Boolean)
  • 字符串(String)
  • 数值(Number)
  • 对象(Object)
生成Symbol值

Symbol值是通过Symbol函数生成

const s = Symbol();

console.log(typeof s); // 'symbol'
console.log(s); // 'Symbol()'

注意:由于Symbol值不是对象,所以不能使用new命令,否则会报错。

函数Symbol可以接受一个字符串作为参数,这个参数表示对Symbol实例的描述,可以用于在控制台显示或者在转成字符串时比较容易区别。

const s1 = Symbol('foo');
console.log(s1); // Symbol('foo')
console.log(s1.toString()); // 'Symbol('foo')'

当Symbol 的参数是一个对象,就会自动调用这个对象的toString()方法,将其转为字符串,然后生成一个Symbol值。

const obj = {
  toString() {
		return 'abc';
  }
}
const sym = Symbol(obj);
console.log(sym); // Symbol(abc)

注意:Symbol函数的参数指示表示当前Symbol值的描述。两个参数相同的Symbol函数返回值是不相等的

let s1 = Symbol();
let s2 = Symbol();

console.log(s1 === s2); // false

let s3 = Symbol();
let s4 = Symbol();

console.log(s3 === s4); // false
Symbol 值不能与其他类型的值进行运算,会报错
let sym = Symbol('abc');
console.log('this symbol is ' + sym); // 报错 TypeError: can't convert symbol to string
Symbol值可以显示转换成字符串
let sym = Symbol('abc');
console.log(String(sym)); // 'Symbol(abc)';
console.log(sym.toString()); // 'Symbol(abc)'; 
Symbol值可以显示转换成布尔值,但不能转成数值
let sym = Symbol();
console.log(Boolean(sym)); // true
console.log(!sym); // false

Symbol.prototype.description

创建Symbol的时候,可以通过参数添加 Symbol 的描述

const sym = Symbol('abc');

上面sym的描述就是foo

  • 在***ES2019***之前只能通过转换成字符串来读取这个描述信息
const sym = Symbol('abc');
console.log(String(sym)); // 'Symbol(abc)'
console.log(sym.toString()); // 'Symbol(abc)'
  • 在***ES2019***中提供了一个实例的属性description,直接返回Symbol的描述
const sym = Symbol('abc');
console.log(sym.description); // 'abc'

作为属性名的Symbol

由于每一个Symbol 值都不相等,所以 Symbol 值可以作为标识符,用于对象的属性名,就可以保证不会出现同名的属性。

const sym = Symbol();

// 第一种写法
const a = {};
a[sym] = 'abc';

// 第二种写法
const a ={
  [sym]: 'abc';
}

// 第三种写法
const a = {};
Object.defineProperty(a, sym, { value: 'abc'});

console.log(a[sym]); // 'abc'
需要注意
  • Symbol 值作为对象属性名时不能用点运算符
const sym = Symbol();
const a = {};

a.sym = 'abc';
console.log(a[sym]); // undefined
console.log(a['sym']); // 'abc'

上面的代码中,因为点运算符后面总是字符串,所以不会使用sym作为标识符,从而导致这里的属性名为一个字符串,而不是Symbol值。

  • 在对象内部,使用Symbol值定义属性时,Symbol 值必须放在方括号之中
const sym = Symbol();
let obj = {
  [sym]: function(arg){
    ...
  }
}

当这里的sym不在方括号中,这个属性的键名就是字符串s,而不是s变量所代表的Symbol值。

采用增强的对象写法,上面的obj也可以写的简洁一点

let obj = {
  [sym](arg){
    ...
  }
}

属性名的遍历

Symbol作为属性名时,使用for...infor...ofObject.keys()Object.getOwnPropertyNames()JSON.stringify()都找不到Symbol的属性。

但是 Symbol作为属性名 也不是私有属性。

通过方法Object.getOwnPropertySymbols()来获取指定对象的所欲Symbol属性名,Object.getOwnPropertySymbols()会返回一个元素时当前对象的所有用作属性名的Symbol值的数组。

const obj = {};
const a = Symbol('a');
const b = Symbol('b');
obj[a] = 'abc';
obj[b] = 'def';

const objectSymbols = Object.getOwnPropertySymbols(obj);

console.log(objectSymbols); // [Symbol(a), Symbol(b)]

通过方法Reflect.ownKeys()也可以获得所有类型的键名,包括常规键名和Symbol键名。

const obj = {
  [Symbol('a')]: 1,
  enum: 2,
};
console.log(obj); ['enum',Symbol('a')]

由于以Symbol 值作为键名,不会被常规方法遍历到,所以可以利用这个特性为对象定义一些非私有,但又只用于内部的方法

Symbol.for() & Symbol.keyFor()

  • Symbol.for()

方法 Symbol.for()接受一个字符串作为参数,然后搜索有没有以这个参数作为名称的Symbol值。如果有,就返回这个Symbol值,如果没有就新建一个以这个参数为名称的Symbol值,并将其注册到全局。

const s1 = Symbol.for('abc');
const s2 = Symbol.for('abc');

console.log(s1); // Symbol(abc)
console.log(s1 === s2); // true;
  • Symbol.for()Symbol()的区别

方法Symbol.for()Symbol()都会生成新的Symbol,Symbol.for()会先在全局环境中搜索,Symbol()不会,并且Symbol.for()不会每次调用就会返回一个新的Symbol类型的值,而是去检查指定的key是否存在,在指定的key不存在的情况下才会创建一个新的。Symbol.for()会将创建的Symbol类型的值记录到全局环境,Symbol()不会记录到全局环境。

  • Symbol.keyFor()

方法Symbol.keyFor()方法返回一个已经登记在全局的Symbol类型值的key.

备注:本文是自己学习阮一峰老师的《ECMAScript 6 入门》所做的笔记,大部分例子来源于此书。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值