彦祖啊 發表於 2026-3-5 16:47:00

探索JavaScript的秘密令牌:独一无二的`Symbol`数据类型

<h1 data-id="heading-0">🧑‍💻 写在开头</h1>
<p>点赞 + 收藏 === 学会🤣🤣🤣</p>
<div>
<div>
<h4 data-id="heading-0">引言</h4>
<p>在JavaScript的广阔世界中,数据类型构成了其最基础的语法元素。随着ES6的发布,这个大家庭迎来了两位新成员:<code>BigInt</code>和<code>Symbol</code>。如果说<code>BigInt</code>是为了解决大数运算的精度问题,那么<code>Symbol</code>的诞生,则像是一把为对象属性开启“隐私空间”和“唯一命名”的神奇钥匙。本文将带你深入理解这个“独一无二”的简单数据类型。</p>
<h4 data-id="heading-1">一、认识<code>Symbol</code>:一种新的简单数据类型</h4>
<p>JavaScript的八种数据类型,是每一位开发者的基本功,常被戏称为“七上八下”:</p>
<ul>
<li>
<p><strong>简单数据类型 (7种)</strong> :</p>
<ul>
<li><strong>传统</strong>:<code>number</code>、<code>boolean</code>、<code>string</code>、<code>null</code>、<code>undefined</code></li>
<li><strong>ES6新增</strong>:<code>bigint</code>、<code>symbol</code></li>
</ul>
</li>
<li>
<p><strong>复杂数据类型 (1种)</strong> :<code>object</code></p>
</li>
</ul>
<p><code>Symbol</code>虽然用起来<strong>有点像构造函数</strong>(<code>Symbol()</code>),但它本质上是<strong>简单数据类型</strong>。你可以通过<code>typeof</code>操作符来验证这一点。</p>
</div>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">// 1.js
const id1 = Symbol();
console.log(typeof id1); // 输出:symbol</pre>
</div>
<h4 data-id="heading-2">二、<code>Symbol</code>的核心特性:绝对的独一无二</h4>
<p><code>Symbol</code>最核心、最迷人的特性,就是它的“独一无二性”。每次调用<code>Symbol()</code>函数,都会返回一个全新的、与其他任何Symbol都不同的值,即使它们拥有相同的描述(label)。</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">// 1.js
const id1 = Symbol();
const id2 = Symbol();
console.log(id1 === id2); // 输出:false

// 2.js
const s1 = Symbol('二哈');
const s2 = Symbol('二哈');
console.log(s1 === s2); // 输出:false</pre>
</div>
<div>
<div>
<p>你可以为<code>Symbol</code>传入一个可选的字符串参数作为<strong>描述(label)</strong> ,例如<code>Symbol('descrption')</code>。这个描述仅仅是为了调试时方便识别,它<strong>不会影响Symbol的唯一性</strong>。两个描述相同的Symbol,依然是两个完全不同的值。这就像给两把不同的锁都贴上了“书房”的标签,但锁的齿纹(值)完全不同。</p>
<h4 data-id="heading-3">三、<code>Symbol</code>的核心应用:作为对象属性的唯一键</h4>
<p><code>Symbol</code>最主要、最实用的场景,就是<strong>作为对象的属性键(key)</strong> 。在ES6之前,对象的键只能是字符串,这在一个复杂、多人协作的代码库中极易引发命名冲突。</p>
<p>JavaScript是动态语言,任何人都可以轻松修改对象的属性。当项目代码庞大时,你可能会无意中覆盖掉他人定义的重要属性,或者自己的属性被他人覆盖,造成难以排查的Bug。</p>
<p><code>Symbol</code>的引入,就是为了解决这个问题。用<code>Symbol</code>作为属性名,可以创造出<strong>绝对安全的、不会与任何字符串属性或其他Symbol属性冲突的私有属性</strong>。</p>
<p><strong>1. 如何定义Symbol属性?</strong></p>
<p>你需要使用<strong>计算属性名</strong>的语法,在<code>[]</code>中写入Symbol变量。</p>
</div>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">// 2.js
const secretKey = Symbol('secret'); // 创建一个Symbol
console.log(secretKey, '//////'); // Symbol(secret) //////

const a = 'ecut';
const user = {
    : '111222', // 使用Symbol作为键
    email: '123456@qq.com',
    name: '张三',
    'a': '456', // 字符串'a'作为键
    : '123'// 使用变量a的值`'ecut'`作为键,相当于 `ecut: '123'`
};
console.log(user.ecut, user); // 输出:123 123</pre>
</div>
<div>
<div>
<p><strong>2. Symbol属性的独特优势</strong></p>
<ul>
<li><strong>命名安全</strong>:<code>secretKey</code>这个属性是独一无二的,全局任何地方都无法用<code></code>以外的其他Symbol访问到它,也无法用字符串<code>'secretKey'</code>来访问,这避免了属性被意外覆盖。</li>
<li><strong>标签不影响唯一性</strong>:即使两个<code>Symbol</code>描述相同,它们作为键也是互不冲突的。</li>
</ul>
</div>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">// 3.html
const classRoom = {
    : {grade: 50, gender: 'male'},
    : {grade: 80, gender: 'female'},
    // 即使标签(描述)和上面一样,这也是一个新的、独立的属性
    : {grade: 85, gender: 'female'},
    "dl": ["张三","李四"]
};</pre>
</div>
<div>
<div>
<p>上述代码中,第二个<code></code>并没有覆盖第一个,而是创建了一个全新的属性,完美解决了同名标签可能带来的冲突。</p>
<p><strong>3. 枚举与遍历:Symbol的“隐藏”特性</strong></p>
<p><code>Symbol</code>属性还有一个重要特性:<strong>它们不会被常规的遍历方法枚举到</strong>。例如,<code>for...in</code>循环、<code>Object.keys()</code>、<code>Object.values()</code>、<code>Object.entries()</code>以及<code>JSON.stringify()</code>都会“忽略”Symbol属性。</p>
</div>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">// 3.html
for (const person in classRoom) {
    console.log(classRoom, '////'); // 只会打印出 "dl" 的值
}</pre>
</div>
<p>这使得Symbol属性具备了一定的“私有”和“内置”属性特征,不会被轻易暴露出去。</p>
<p>如果你需要获取对象中所有的<code>Symbol</code>属性,必须使用专门的方法:</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">// 3.html
const syms = Object.getOwnPropertySymbols(classRoom); // 返回一个包含对象自身所有Symbol键的数组
console.log(syms); // 打印出

// 可以结合map方法获取这些属性的值
const data = syms.map(sym =&gt; classRoom);
console.log(data); // 打印出三个学生的对象数组</pre>
</div>
<div>
<div>
<h4 data-id="heading-4">四、总结</h4>
<p><code>Symbol</code>是ES6为解决JavaScript长期存在的属性命名冲突和元编程问题而引入的一种优雅方案。它:</p>
<ol>
<li><strong>是简单数据类型</strong>,独一无二。</li>
<li><strong>是创建对象唯一键的理想选择</strong>,尤其在多人协作和库的开发中,能有效保证属性安全。</li>
<li><strong>具有“半隐藏”特性</strong>,不会被常规方法枚举,需用<code>Object.getOwnPropertySymbols()</code>获取。</li>
</ol>
<p>掌握了<code>Symbol</code>,你就拥有了在JavaScript对象中创建“命名空间”和“内部插槽”的能力,让你的代码结构更清晰、更健壮。</p>
</div>
<div>
<h3 id="tid-D8HBxE">如果对您有所帮助,欢迎您点个关注,我会定时更新技术文档,大家一起讨论学习,一起进步。</h3>
</div>
<p><em><img src="https://img2024.cnblogs.com/blog/2149129/202501/2149129-20250122165814748-630765389.png" alt="" loading="lazy"></em></p>
</div>
</div>
</div>
</div>
</div><br><br>
来源:https://www.cnblogs.com/smileZAZ/p/19674000
頁: [1]
查看完整版本: 探索JavaScript的秘密令牌:独一无二的`Symbol`数据类型