ES2015 Symbol 一种全新的原始数据类型

ES2015引入了新的原始数据类型Symbol,保证了属性名的唯一性,避免了字符串属性名可能导致的冲突。Symbol可以通过描述文本区分不同的值,并用于创建对象的私有属性。此外,Symbol还提供了内置常量和静态方法,允许对象实现JS内置接口。尽管传统遍历方法无法获取Symbol属性,但Object.getOwnPropertySymbols()可用来获取这些私有属性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、Symbol 的基本使用

在ES2015之前,对象的属性名都是字符串,而字符串有可能会重复,重复的话有可能会有冲突。

看一个例子,比如有3个js文件

// share.js=========
const cache = {}
// a.js=========
cache['foo'] = '123'
// b.js=========
cache['foo'] = Math.random()

console.log(catch)

现在我们大量使用第三方库,很多时候需要自己去扩展。如果出现属性重复怎么办呢?

ES2015之前的解决方案:约定

给属性名添加特定前缀,比如说Vue内部也使用$和_作为内部方法或属性。

// share.js=========
const cache = {}
// a.js=========
cache['a_foo'] = '123'
// b.js=========
cache['b_foo'] = Math.random()

console.log(catch)

在ES2015中,新增了一种原始数据类型Symbol —— 表示独一无二的值。

基本使用:

const s =  Symbol()
console.log(s)// Symbol()
console.log(typeof s)// symbol

通过Symbol创建的值都是独一无二的,它永远不会重复:

console.log(Symbol() === Symbol())//false
console.log(Symbol('foo') === Symbol('foo'))//false

Symbol 可以传入一个字符串,作为这个值的描述文本,用于区分 :

console.log(Symbol('foo'))// Symbol(foo)
console.log(Symbol('baz'))// Symbol(baz)

从ES2015开始,对象就可以使用symbol类型的值作为属性名

新增对象的属性名可以是2种类型:stringsymbol


const obj = {
	[Symbol()]:123,
  [Symbol()]:456,
}
obj[Symbol()] = 789;
console.log(obj)//{[Symbol()]:123,[Symbol()]:456,[Symbol()]:789}

二、Symbol目前最主要的作用——为对象添加独一无二的属性名

以前对私有成员都是靠约定,例如我们约定用下划线_开头就表示是私有成员,我们约定外界不允许访问对象中以下划线开头的成员。

现在,我们可以使用Symbol来创建私有成员的属性名

用Symbol来实现私有成员的属性名:

// a.js=========对外暴露一个对象person
const name = Symbol()
const person = {
  [name]:'zce',
  say(){
    console.log(this[name])
  }
}

// b.js=========
person.say() // zce

Symbol目前最主要的作用就是为对象添加独一无二的属性名

截止到ES2019,一共定义了7种数据类型:6种原始数据类型 (string、number、null、undefined、boolean、symbol) +一种复杂数据类型 object

未来还会添加一种原始数据类型BigInt,标准化过后就是8种数据类型了。

三、Symbol 的其他相关内容

如果需要在全局去复用一个Symbol,可以用全局变量,或者用Symbol类型提供的一个静态方法Symbol.for()去实现

Symbol.for()要求传入的参数是字符串string,如果传入的参数是其他类型,会被自动转为字符串string

const s1 = Symbol.for('foo')
const s2 = Symbol.for('foo')
console.log(s1 === s2)// true

console.log(Symbol.for('true') ===  Symbol.for(true)// true
Symbol提供了很多内置的symbol常量,用来作为内部方法的标识,这些标识符可以让自定义对象去实现一些js当中内置的接口

例如:

  • Symbol.iterator
  • Symbol.hasInstance
  • Symbol.toStringTag

const obj = {}
console.log(obj.toString()) // [object Object] 

[object Object] 这个字符串称为对象的toString标签

如果想自定义对象的toString标签,可以在对象中添加一个特定的成员来标识

如果用字符串作为标识符,有可能会和内部的成员产生重复

ES2015 要求我们使用symbol值来实现这样的接口:

const obj = {
  // toStringTag是内置的Symbol常量
  [Symbol.toStringTag]:'XObject'
}
console.log(obj.toString()) // [object XObject]
使用Symbol做作为属性名

使用传统的for in循环、Object.keys()JSON.stringify()都拿不到symbol 类型的属性

这个特性使得Symbol类型的属性特别适合用来作为对象的私有属性

const obj = {
	[Symbol()]:'symbol value',
    foo:'normal value'
}
// 那怎么获取symbol 类型的属性?
 
Object.getOwnPropertySymbols() // 使用方法类似于Object.keys() 

console.log(Object.getOwnPropertySymbols(obj));//  [ Symbol() ]
  • Object.keys()——获取对象中所有字符串类型的属性名

  • Object.getOwnPropertySymbols()——获取对象中所有symbol类型的属性名

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值