本文详解JavaScript ES6引入的第七种基本数据类型Symbol。阐述其唯一性、不可运算及遍历特性,对比对象与字符串的内存引用差异。重点解析Symbol.for()的全局登记机制与Symbol.keyFor()的描述获取方法,展示Symbol作为对象属性名的多种写法及注意事项。
一、Symbol类型的定义
Symbol是ES6引入的全新基本数据类型,旨在生成独一无二的标识值。作为JavaScript的第七种数据类型,它与undefined、null、Number、String、Boolean及Object并列存在。
Symbol的核心特性包括:
- 其值具有唯一性,主要用于解决属性命名冲突问题。
- Symbol值不具备与其他数据进行数学运算的能力。
- 以Symbol定义的对象属性无法通过for...in循环进行遍历,但可通过Reflect.ownKeys方法获取对象的所有键名。
基础使用场景:
let a = Symbol("末晨曦吖");
console.log(a); // Symbol(末晨曦吖)
console.log(typeof a); //symbol
// 相同参数 Symbol() 返回的值不相等
let b = Symbol("末晨曦吖");
console.log(a === b); //false
为何相同参数调用Symbol()返回的值互不相等?
当使用Symbol()创建Symbol类型值并赋值给变量a时,即获得内存中独一无二的引用。除变量a外,任何作用域内均无法通过相同参数重新创建该值,故即使使用相同参数创建变量b,两者仍不相等。
尽管a和b均通过Symbol()生成,但在内存中的表现如下:

变量a实际持有内存中某块地址的唯一引用。若不借助变量a,无法再次获取该地址。因此:
a !== b; //a和b持有的是两块内存的引用
const c = a; //手动把a里保存的地址保存在c变量中
a === c; //c和a现在指向同一块内存,因为它们保存了同样的地址

此行为虽显晦涩,但遵循与对象相同的规则,例如:
let a = {};
let b = {};
a !== b; //a和b各自被分配了不同的内存,因此它们保存了不同的地址
//借助变量a,变量c拿到了a指向的那个对象的地址,因此两者相等
let c = a;
a === c;
然而,同为基本数据类型的字符串并不遵循此规则。例如:
let a = "123";
let b = "123";
a === b; //返回true。两者在常量区引用同一个字符串

首先通过变量a在内存中创建字符串“123”,随后在不借助a的情况下,通过var b = "123"获取对“123”的引用,两者指向内存中的同一地址。
因此,a无法阻止其他变量获取其保存的地址(前提是不通过a)。但对于var a = Symbol(),a保存的值是唯一的,因为除a外无法获取该值。这正是Symbol的本质。
二、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 a = {};
let name = Symbol();
a.name = 'lili';
a[name] = 'lucy';
console.log(a.name,a[name]);//lili,lucy
Symbol值作为属性名时,该属性还是公开属性,不是私有属性。
三、Symbol相关方法
1、Symbol.for()方法
已知Symbol()创建的两个变量永远不相等。若需复用同一Symbol,可避免逐一比较。ES6提供了Symbol.for()方法以解决此问题。
参数为symbol类型的描述信息,区别于Symbol(),此参数仅限字符串或undefined。若已存在则返回该symbol,否则创建并返回新symbol,代码如下
let name = Symbol.for("末晨曦");
let name1 = Symbol.for("末晨曦");
console.log(name === name1); // true
注意,在创建描述信息为"末晨曦"的变量时,应使用for而非Symbol()。若首次使用Symbol()创建,for会再次创建新实例,二者不相等,代码如下:
let name = Symbol("末晨曦");
let name1 = Symbol.for("末晨曦");
console.log(name === name1); // false
原因在于Symbol.for()具备登记机制,仅检查通过for创建的symbol,不检查Symbol()创建的实例。
2、Symbol.keyFor()方法
该方法接收通过Symbol.for()创建的symbol变量,返回其描述信息。
let name = Symbol.for("末晨曦");
console.log(Symbol.keyFor(name)); // "末晨曦"
let name1 = Symbol("末晨曦");
console.log(Symbol.keyFor(name1)); // undefined 不能查找Symbol()创建的变量至此,关于JavaScript第七种数据类型Symbol的用法详解介绍完毕,更多相关JavaScript Symbol内容请搜索本站以前的文章或继续浏览下面的相关文章希望大家以后多多支持本站!