【ES6基础】Symbol介绍:独一无二的值

640?wx_fmt=jpeg

开篇


ES6之前我们都清楚JS有六种数据类型:Undefined、Null、布尔值(Boolean)、字符串(String)、数值(Number)、对象(Object),今天笔者讲的Symbol类型是ES6才加入的,它最大的特点就如标题所说“独一无二”。


本篇文章将从以下方面进行介绍:

  • 值类型和引用类型介绍

  • 如何声明一个Symbol?

  • 为什么要有Symbol?

  • Symbol的常用用法

  • 内置常用Symbol值的用法


本篇文章阅读时间预计15分钟


01

值类型和引用类型介绍

在了解Symbol之前,我们需要了解下JS的数据类型,在JS中数据类型分为两类:值类型和引用类型。

  • 值类型:数值型(Number),字符类型(String),布尔值型(Boolean),null 和 underfined

  • 引用类型:对象(Object)


所谓的值类型可以这样理解:变量之间的互相赋值,是指开辟一块新的内存空间,将变量值赋给新变量保存到新开辟的内存里面;之后两个变量的值变动互不影响。 如下段代码所示:

let weChatName ="前端达人";
//开辟一块内存空间保存变量 weChatName 的值“前端达人”;
let touTiao =weChatName;
//给变量 touTiao 开辟一块新的内存空间,将 weChatName 的值 “前端达人” 赋值一份保存到新的内存里;
//weChatName 和 touTiao 的值以后无论如何变化,都不会影响到对方的值;

一些语言,比如 C,有引用传递和值传递的概念。JS 也有类似的概念,它是根据传递的数据类型推断的。如果将值传递给函数,则重新分配该值不会修改调用位置中的值。但是,如果你修改的是引用类型,那么修改后的值也将在调用它的地方被修改。


所谓的引用类型可以这样理解:变量之间的互相赋值,只是指针的交换,而并非将对象复制一份给新的变量,对象依然还是只有一个,只是多了一个指引~~;如下段代码所示:

let weChat = { name: "前端达人", regYear:"2014" };
//需要开辟内存空间保存对象,变量 weChat 的值是一个地址,这个地址指向保存对象的空间;
let touTiao= weChat;
// 将 weChat 的指引地址赋值给 touTiao,而并非复制一给对象且新开一块内存空间来保存;
weChat.regYear="2018";
console.log(touTiao);
//output:{ name: '前端达人', regYear: '2018' }
// 这个时候通过 weChat 来修改对象的属性,则通过 touTiao 来查看属性时对象属性已经发生改变;

那Symbol是什么数据类型呢?这里笔者先告诉大家是值类型,下面会有详细的介绍。


02

如何声明一个Symbol?

Symbol最大的特点就如本篇文章的标题一样:独一无二。这个独一无二怎么解释呢?就好比双胞胎,外表看不出差别,但是相对个体比如性格爱好还是有差异的,每个人都是独一无二。Symbol表示独一无二的值,是一种互不等价标识,声明Symbol十分简单,如下段代码所示:

const s = Symbol();

Symbol([description]) 声明方式,支持一个可选参数,只是用于描述,方便我们开发调试而已。每次执行Symbol()都会生成一个独一无二的Symbol值,如下段代码所示:

let s1 = Symbol("My Symbol");
let s2 = Symbol("My Symbol");
console.log(s1 === s2); // Outputs false”

由此可见,即使Symbol的描述值参数相同,它们的值也不相同,描述值仅仅是起描述的作用,不会对Symbol值本身起到任何的改变。关于描述值需要注意的一点:接受除Symbol值以外所有的值,怎么理解呢,请看下段代码所示:

const symbol = Symbol();
const symbolWithString=Symbol('前端达人');
//Symbol(前端达人)
const SymbolWithNum=Symbol(3.14);
//Symbol(3.14)
const SymbolWithObj=Symbol({ foo:'bar'});
//Symbol([object Object])
const anotherSymbol=Symbol(symbol);
//TypeError: Cannot convert a Symbol value to a string

接下来笔者来详细解释下,为什么Symbol是值类型,而不是引用类型。Symbol函数并不是构造函数,因此不能使用new方法来生成一个Symbol对象,否则编译器会抛出异常,如执行下段代码所示:

new Symbol();
//TypeError: Symbol is not a constructor

由此可见,Symbol是一种值类型而非引用类型,这就意味着如果将Symbol作为参数传值的话,将会是值传值而非引用传值,如下段代码所示(值的改变没有互相影响):

const symbol=Symbol('前端达人');
function fn1(_symbol) {
return _symbol==symbol;
}
console.log(fn1(symbol));
//output:true;
function fn2(_symbol) {
_symbol=null;
console.log(_symbol);
}
fn2(symbol);
//output:null;
console.log(symbol);
//Symbol(前端达人)


03

为什么要有Symbol?

介绍了这么多,Symbol存在的意义是什么?笔者先举个简单的业务场景:


在前端的JavaScript应用开发中,需要先通过渲染引擎所提供的API来获取一个DOM元素对象,并保留在JavaScript运行时中。因为业务需要,需要通过一个第三方库对这个DOM元素对象进行一些修饰和调整,即对该DOM元素对象进行一些新属性的插入。


而后来因为新需求的出现,需要再次利用另外一个第三方库对同一个DOM元素对象进行修饰。但非常不巧的是这个第三方库同样需要对该DOM元素对象进行属性插入,而恰好这个库所需要操作的属性与前一个第三方库所操作的属性相同。这种情况下就很有可能会出现两个第三方库都无法正常运行的现象,而使用这些第三方库的开发者却难以进行定位和修复。


针对上述问题, Symbol可以提供一种良好的解决方案。这是因为Symbol的实例值带有互不等价的特性,即任意两个Symbol值都不相等。在ES2015标准中,字面量对象除了可以使用字符串、数字作为属性键以外,还可以使用Symbol作为属性键,因此便可以利用Symbol值的互不等价特性来实现属性操作的互不干扰了。


04

Symbol的常用用法


1、判断是否是Symbol


如何判断一个变量是不是Symbol类型呢?目前唯一的方法就是使用typeof,如下段代码所示:

const s = Symbol();
console.log(typeof s);
//Outputs "symbol”


2、用作对象的属性


通常我们使用字符串定义对象的属性(Key),有了Symbol类型后,我们当然可以使用Symbol作为对象的属性,唯一不同的地方,我们需要使用[]语法定义属性,如下段代码所示:

const WECHAT_NAME = Symbol();
const WECHAT_REG = Symbol();
let obj = {
[WECHAT_NAME]: "前端达人";
}
obj[WECHAT_REG] = 2014;
console.log(obj[WECHAT_NAME]);
//output: 前端达人
console.log(obj[
  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值