JavaScript ES6 Symbol 数据类型详解:语法、全局注册与内置符号
本文深入解析 JavaScript ES6 新增的 Symbol 数据类型。内容涵盖 Symbol 的基本语法、作为唯一属性名的使用方法、Symbol.for 与 Symbol.keyFor 的全局注册机制,以及 Object.getOwnPropertySymbols 等遍历技巧。同时详细列举了 Iterator、String 匹配、Instanceof 等 11 个内置 Symbol 的具体应用场景,帮助开发者掌握这一核心特性。
Symbol 数据类型概述
介绍
Symbol 是 JavaScript 中一种特殊且不可变的数据类型,主要用于生成独一无二的值,常作为对象属性的标识符。Symbol 对象本质上是 symbol 原始数据类型的隐式包装器。
作为 JavaScript 语言的第七种数据类型,Symbol 补充了前六种类型:Undefined、Null、Boolean、String、Number 和 Object。
Symbol 语法与基础用法
语法
Symbol([description])
Parameters
description:这是一个可选的字符串参数,用于描述或调试符号,但不会暴露符号本身的值。若不提供此参数,控制台打印时仅显示“Symbol”,难以区分不同实例。
demo
var s1 = Symbol('symbol1');
s1 //Symbol(symbol1);
由于每次调用 Symbol 函数都会返回一个独一无二的值,因此任意两个通过 Symbol 生成的值都不相等。
//无参数
var s1 = Symbol();
var s2 = Symbol();
s1 === s2 // false
//有参数
var s1 = Symbol('symbol');
var s2 = Symbol('symbol');
s1 === s2 //false
Symbol 作为对象属性名
作为属性名的 Symbol
鉴于每个 Symbol 值都是唯一的,将其用作对象属性名是极佳的选择,可有效避免属性名冲突。
定义方式:
let symbolProp = Symbol();
var obj = {};
obj[symbolProp] = 'hello Symbol';
//或者
var obj = {
[symbolProp] : 'hello Symbol';
}
//或者
var obj = {};
Object.defineProperty(obj,symbolProp,{value : 'hello Symbol'});
注意:
在定义属性时,必须将 Symbol 值置于方括号 [] 内,否则键名会被视为普通字符串而非 Symbol 值。同理,访问 Symbol 属性时不能使用点运算符(.),因为点运算符后跟随的总是字符串,无法解析 Symbol 标识符所指向的值。
Symbol 定义常量与消除魔术字符串
Symbol类型定义常量
使用 Symbol 值定义常量的最大优势在于其唯一性,其他任何值都不可能与之相同。这使得 Symbol 成为设计 switch 语句的理想选择,有助于消除“魔术字符串”。(此处留给读者思考,如有疑问可留言交流)
Symbol.for 与 Symbol.keyFor 全局注册机制
Symbol.for(),Symbol.keyFor()
Symbol.for()
对于 Symbol.for 方法需要记住两点:
Symbol.for()所返回的 Symbol 值作用域覆盖整个代码库(包括不同的 iframe 或 Service Worker),属于全局变量,首次生成时即会进行登记。- 调用
Symbol.for()时,系统会在全局环境中检索给定的 key 是否存在;若不存在则新建一个值。相比之下,Symbol()不会进行全局检索,Symbol()每次调用均返回不同的新值。
Symbol.for('foo') === Symbol.for('foo'); //true
Symbol('foo') === Symbol('foo'); //false
Symbol.keyFor()
Symbol.keyFor 方法用于返回已登记 Symbol 值的 key。
var s1 = Symbol.for('foo');
Symbol.keyFor(s1) //"foo"
var s2 = Symbol('foo');
Symbol.keyFor(s2);//undefiend
在上面的代码示例中,变量 s2 属于未登记的 Symbol 值,因此 Symbol.keyFor(s2) 返回 undefined。
Symbol 属性名的遍历方法
属性名的遍历
Symbol 作为属性名虽非私有属性,但在 for…in、for…of 循环中,Object.keys() 和 Object.getOwnPropertyNames() 均无法获取到 Symbol 属性。通常可通过以下两种方法实现 Symbol 属性的遍历。
Object.getOwnPropertySymbols 方法返回一个数组,包含当前对象所有 Symbol 值的属性。
Reflect.ownKeys() 可以返回所有类型的键名,既包括常规字符串键名,也包括 Symbol 键名。
下面给出一个例子来解释上面所有的。
var obj = {};
var a = Symbol('a');
var b = Symbol('b');
obj[a] = 'hello';
obj[b] = 'world';
//获取不到
for(var i in obj){
console.log(i); //无输出
}
Object.getOwnPropertyNames(obj);//[]
//可以获取
var objectSymbols = Object.getOwnPropertySymbols(obj);
objectSymbols// [Symbol(a), Symbol(b)]
Reflect.ownKeys(obj);//[Symbol(a), Symbol(b)]
以 Symbol 值作为名称的属性不会被常规遍历方法获取。我们可以利用这一特性,为对象定义一些非私有但希望仅用于内部的方法。
var size = Symbol('size');
class Collection {
constructor(){
this[size] = 0;
}
add(item){
this[this[size]] = item;
this[size]++;
}
static sizeOf(instance){
return instance[size];
}
}
var x = new Collection();
Collection.sizeOf(x); //0
x.add('foo');
Collection.sizeOf(x); //1
Object.keys(x)//['0']
Object.getOwnPropertyNames(x) //['0']
Object.getOwnPropertySymbols(x) //[Symbol(size)]
在上面的代码中,对象 x 的 size 属性是一个 Symbol 值,因此 Object.keys(x) 和 Object.getOwnPropertyNames(x) 都无法获取它。这就造成了一种非私有的内部方法的效果。如果对 ES6 定义类方面还不清楚的,可以先不看这段,或者自己查查资料,后面的文章我也会分享出来,总的来说现在 JavaScript 的新标准越来越像 Java 了,比如新增的 const、let 块级作用域,class 定义类等等。
JavaScript 内置 Symbol 详解
内置的Symbol值
除了开发者自定义的 Symbol 值外,JavaScript 还提供了一些表示内部语言行为的内置 Symbol,这些在 ECMAScript 5 及以前并未暴露给开发者。可通过下列属性访问这些内置 Symbol:
1、Symbol.iterator
返回对象的默认迭代器方法,被 for…of 循环使用。
2、Symbol.math
与字符串匹配的方法,也用于判断对象是否可以用作正则表达式,被 String.prototype.match() 使用。
3、Symbol.replace
一种取代匹配字符串子串的方法,被 String.prototype.replace() 使用。
4、Symbol.search
返回与正则表达式匹配的字符串内索引的方法,被 String.prototype.search() 使用。
5、Symbol.split
在与正则表达式匹配的索引处拆分字符串的方法,被 String.prototype.split() 使用。
6、Symbol.hasInstance
确定构造函数对象是否将对象作为实例识别的方法,被 instanceof 操作符使用。
7、Symbol.isConcatSpreadable
一个布尔值,指示对象是否应该被扁平化为数组元素,被 Array.prototype.concat() 使用。
8、Symbol.unscopables
从关联对象的环境绑定中排除其自身和继承的属性名称的对象值,被 with 语句使用。
9、Symbol.species
用于创建派生对象的构造函数。
10、Symbol.toPrimitive
将对象转换为原始值的方法。
11、Symbol.toStringTag
用于对象的默认描述的字符串值,被 Object.prototype.toString() 使用。
这里未给出具体示例,针对这 11 个属性,建议读者主动深入研究,这对理解相关方法非常有用。
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对本站的支持。
JS大数值转字符串出现科学计数法怎么办
2026-11-05 17:09:21
JS split切割后出现空字符串怎么过滤
2026-11-05 16:00:30
在 React 或 Vue 项目中封装使用 JS 节流防抖
2026-11-05 15:27:29
JavaScript中怎么将带小数的字符串转为整数?
2026-11-05 14:32:38
怎么用JavaScript策略模式重构电商促销计算逻辑?
2026-11-05 14:01:09
