Javascript学习路之Symbol

244 阅读4分钟

Symbol:JavaScript 中的唯一值与对象键

引言

在 JavaScript 的世界里,Symbol 是Javascript中的一种基本数据类型,它可以创建独一无二并且不可以改变的数据。每个创建的Symbol都是独一无二的。Symbol 主要用于对象属性键的定义,以确保这些属性不会与其他属性发生命名冲突。这使得 Symbol 成为了处理对象属性时的理想选择,尤其是在大型项目中,可以防止属性名称冲突的问题。下面我们将深入探讨 Symbol 的特性、用法及其在对象中的作用。

唯一值

Symbol 可以通过调用 symbol() 函数来声明,同时你可以给它一个可选的标签(label),但这不影响它的唯一性。每次当你创建一个新的 Symbol 时,即使你使用了相同的标签,它们仍然是两个不同的 Symbol 实例。这种唯一性让 Symbol 在复杂对象结构中作为属性名时非常有用,因为它保证了不会与其他属性发生命名冲突,也不会被意外覆盖。

对象字面量中的应用

Symbol 还可以代替字符串作为对象的键(key) 在对象字面量中使用 Symbol 作为键,能够有效地避免由于属性名重复而导致的数据覆盖问题。这对于大厂开发的大规模应用程序来说尤为重要,因为这些应用往往涉及多个团队协作,对象结构复杂且难以维护。通过使用 Symbol,开发者可以安全地为对象添加新的键值对,而不用担心会破坏现有功能。

不可见的键

值得注意的是,像 Object.keys(), Object.values(), 和 Object.entries() 这样的方法,在获取对象的键名、键值或键值对数组时,并不会包括 Symbol 类型的键。这是因为 Symbol 设计的目的就是提供一种不可枚举的方式,用于定义私有属性或内部属性,从而保护数据不被外部代码轻易访问。

可迭代对象与属性描述符

虽然 Symbolenumerable 属性设置为 false,意味着它们不是可枚举的,但我们仍然可以通过特定的方法如 Object.getOwnPropertySymbols() 来获取对象上的所有 Symbol 键。此外,Object.getOwnPropertyDescriptors() 方法允许我们获取对象上所有自身属性(包括 Symbol 类型)的属性描述符。

大厂面试题

当你想要在定时器setTimeout中使用call来立即执行可能会遇到的问题

屏幕截图 2024-12-10 162244.png .call() 确实会立即执行传递给它的函数,并将 this 设置为指定的对象(在这里是 obj),但它只适用于直接调用的函数。对于 setTimeout,它接收的是一个回调函数,这个回调函数会在未来的某个时间点被调用,此时的 this 可能不会是指向 obj 的,因为 setTimeout 的回调函数是在全局作用域中执行的,在浏览器环境中这意味着 this 会指向 window 对象。

那我们要如何解决这个问题呢? 方法一使用箭头函数

屏幕截图 2024-12-10 163007.png 方法二使用bind

屏幕截图 2024-12-10 163016.png 这两种方法都能确保 thissetTimeout 回调中正确指向 obj,从而使得 func1 能够访问到 objname 属性并打印出 "Cherry"

结论

综上所述,Symbol 提供了一种创建唯一标识符的方法,特别适合用作对象属性名,以避免命名冲突和数据覆盖的问题。对于那些需要保护起来不让外部直接访问的属性,Symbol 更是理想的选择。随着项目的增长和复杂度的增加,利用好 Symbol 能够帮助开发者更好地管理和维护代码,在setTimeout定时器中使用call时得注意.call(obj) 是用来立即执行 setTimeout 的回调函数,但这并不是你想要的行为。你希望的是设置 this 的上下文,而不是立即执行该函数。

补充说明 - ownProperty

当提到 ownProperty 或者更准确地说 own property(自有属性),是指直接属于对象自身的属性,而不是继承自原型链的属性。Object.getOwnPropertyDescriptors() 就是用来获取对象自身所有属性(包括那些由 Symbol 定义的属性)的属性描述符。每个描述符包含了一个对象,其中有关于该属性的各种信息,比如配置 (configurable)、可枚举性 (enumerable)、可写性 (writable) 和值 (value) 等等。这对于深入了解对象的内部结构以及进行高级编程操作非常重要。