[译] JavaScript 中为什么会有 Symbol 类型?

简介: [译] JavaScript 中为什么会有 Symbol 类型?

声明

本文转载自:掘金-熊咆龙吟

背景

JavaScript中有两种数据类型:基本数据类型和对象(对象也包括函数),基本数据类型包括简单数据类型,比如Number(从整数到浮点数,从Infinity到NaN都属于Number类型)、Boolean、String、undefined、null(注意尽管typeof null === object,null仍然是一个基本数据类型)。

基本数据类型的值是不可以改变的,即不能更改变量的原始值,当然可以重新对变量进行赋值。例如,代码:

let x = 1;
x++;

虽然,你通过重新赋值改变了变量x的值,但是变量的原始值1仍没有被改变。

一些语言,比如C语言,有按引用传递和按值传递的概念。JavaScript也有类似的概念,它是根据传递数据的类型推断出来的。如果将值传入一个函数,则在函数中重新对它赋值不会修改它在调用位置的值。但是,如果你修改的是基本数据的值,那么修改后的值会在调用它的地方被修改。

考虑下面的例子:

function primitiveMutator(val) {
  val = val + 1;
}
let x = 1;
primitiveMutator(x);
console.log(x); //1
function objectMutator(val) {
  val.prop = val.prop + 1;
}
let obj = {prop: 1};
objectMutator(obj);
console.log(obj.prop); //2

基本数据类型(NaN除外)总是与另一个具有相同值的基本数据类型完全相等。如下:

const first = "abc" + "def";
const second = "ab" + "cd" + "ef";
console.log(first === second);  //true

然而,构造两个值相同的非基本数据类型则得到不相等的结果。我们可以看到发生了什么:

const obj1 = { name: "666"};
const obj2 = {name: "666"};
console.log(obj1 === obj2); //false

对象在JavaScript中扮演着重要的角色,几乎所有地方可以见到它们的身影。对象通常是键值对的集合,然而这种形式的最大限制是:对象的键只能是字符串,知道Symbol出现这一限制才得到解决。如果我们使用非字符串的值作为对象的键,该值会被强制转换为字符串。下面的程序中可以看到这种强制转换:

const obj = {};
obj.foo = "foo";
obj['bar'] = 'bar';
obj[2] = 2;
obj[{}] = 'someobj';
console.log(obj);

image.png

Symbol是什么?

现在既然我们已经知道了基本数据类型是什么,也就终于可以定义Symbol了。

Symbol是不能被重新创建的基本数据类型。在这种情况下,Symbol类似与对象,因为对象创建多个实例也将导致不完全相等的值。但是,Symbol也是基本数据类型,因为它不能被改变。下面是Symbol用法的一个例子:

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

当实例化一个Symbol值时,有一个可选的首选参数,你可以赋值一个字符串。此值用于调试代码,不会真正影响Symbol本身。

const s1 = Symbol('debug');
const str = 'debug';
const s2 = Symbol('xxxy');
console.log(s1 === str); //false
console.log(s1 === s2); //false
console.log(s1); //Symbol(debug)

Symbol作为对象属性

symbol还有一个重要的用法,他们可以被当作对象中的键!下面是一个在对象中使用Symbol作为键的例子:

const obj = {};
const sym = Symbol();
obj[sym] = 'foo';
obj.bar = 'bar';
console.log(obj); 
console.log(sym in obj);
console.log(obj[sym]);
console.log(Object.keys(obj));

image.png


注意,Symbol键不会被在Object.keys()返回。也是为了满足向后兼容性。旧版本的JavaScript中没有Symbol数据类型,因此不应该从旧的Object.keys()方法中被返回。

乍一看,这就像是可以用Symbol在对象上创建私有属性!许多其他编程语言可以在其类中有私有属性,而JavaScript却遗漏了这种功能,长期以来被视为其语法的一种缺点。

不幸的是,与该对象交互的代码仍然可以访问对象那些键为Symbol的属性。甚至是在调用代码自己无法访问Symbol的情况下也有可能发生。例如,Reflect.ownKeys()方法能够得到一个对象的所有键的列表,包括字符串和Symbol:

function tryToAddPrivate(obj) {
  obj[Symbol('Pseudo Private')] = 42;
}
const obj = { prop: 'hello' };
tryToAddPrivate(obj);
console.log(Reflect.ownKeys(obj));
console.log(obj[Reflect.ownKeys(obj)[1]]); // 42


防止属性名冲突

后续请查看原文。。。

相关文章
|
1月前
|
JavaScript
常见函数的4种类型(js的问题)
常见函数的4种类型(js的问题)
11 0
|
2月前
|
JSON JavaScript 前端开发
解决js中Long类型数据在请求与响应过程精度丢失问题(springboot项目中)
解决js中Long类型数据在请求与响应过程精度丢失问题(springboot项目中)
43 0
|
2月前
|
JavaScript 前端开发
javascript中的Symbol
javascript中的Symbol
|
2月前
|
JavaScript 前端开发 开发者
编程笔记 html5&css&js 071 JavaScript Symbol 数据类型
编程笔记 html5&css&js 071 JavaScript Symbol 数据类型
|
1月前
|
JavaScript 前端开发
JavaScript 中如何检测一个变量是一个 String 类型?
JavaScript 中如何检测一个变量是一个 String 类型?
22 2
|
4月前
|
JSON JavaScript 前端开发
抓住异常,解救你的代码世界:你应该了解的 JavaScript 异常类型
抓住异常,解救你的代码世界:你应该了解的 JavaScript 异常类型
|
4天前
|
前端开发 JavaScript 索引
【Web 前端】JS的几种具体异常类型(报错)
【4月更文挑战第22天】【Web 前端】JS的几种具体异常类型(报错)
|
4天前
|
数据可视化 JavaScript 前端开发
Echarts是一个开源的JavaScript可视化库,用于创建各种类型的图表
Echarts是JavaScript的开源可视化库,Python通过Pyecharts库可调用它来绘制图表。示例展示了如何用Pyecharts创建柱状图:定义图表对象,设置标题和坐标轴,添加X轴、Y轴数据,最后渲染展示。Pyecharts还支持折线图、散点图、饼图等多种图表类型,更多详情可查阅官方文档。
16 0
|
29天前
|
JavaScript 前端开发
JavaScript数组的功能内置类型
数组是JavaScript的内置类型,JavaScript数组的功能特别强大。下面简单介绍一下JavaScript数组。
|
1月前
|
存储 JavaScript 前端开发
JavaScript 中松散类型的理解
JavaScript 中松散类型的理解
28 3

热门文章

最新文章