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 设计的目的就是提供一种不可枚举的方式,用于定义私有属性或内部属性,从而保护数据不被外部代码轻易访问。
可迭代对象与属性描述符
虽然 Symbol 的 enumerable 属性设置为 false,意味着它们不是可枚举的,但我们仍然可以通过特定的方法如 Object.getOwnPropertySymbols() 来获取对象上的所有 Symbol 键。此外,Object.getOwnPropertyDescriptors() 方法允许我们获取对象上所有自身属性(包括 Symbol 类型)的属性描述符。
大厂面试题
当你想要在定时器setTimeout中使用call来立即执行可能会遇到的问题
.call() 确实会立即执行传递给它的函数,并将 this 设置为指定的对象(在这里是 obj),但它只适用于直接调用的函数。对于 setTimeout,它接收的是一个回调函数,这个回调函数会在未来的某个时间点被调用,此时的 this 可能不会是指向 obj 的,因为 setTimeout 的回调函数是在全局作用域中执行的,在浏览器环境中这意味着 this 会指向 window 对象。
那我们要如何解决这个问题呢? 方法一使用箭头函数
方法二使用bind
这两种方法都能确保
this 在 setTimeout 回调中正确指向 obj,从而使得 func1 能够访问到 obj 的 name 属性并打印出 "Cherry"。
结论
综上所述,Symbol 提供了一种创建唯一标识符的方法,特别适合用作对象属性名,以避免命名冲突和数据覆盖的问题。对于那些需要保护起来不让外部直接访问的属性,Symbol 更是理想的选择。随着项目的增长和复杂度的增加,利用好 Symbol 能够帮助开发者更好地管理和维护代码,在setTimeout定时器中使用call时得注意.call(obj) 是用来立即执行 setTimeout 的回调函数,但这并不是你想要的行为。你希望的是设置 this 的上下文,而不是立即执行该函数。
补充说明 - ownProperty
当提到 ownProperty 或者更准确地说 own property(自有属性),是指直接属于对象自身的属性,而不是继承自原型链的属性。Object.getOwnPropertyDescriptors() 就是用来获取对象自身所有属性(包括那些由 Symbol 定义的属性)的属性描述符。每个描述符包含了一个对象,其中有关于该属性的各种信息,比如配置 (configurable)、可枚举性 (enumerable)、可写性 (writable) 和值 (value) 等等。这对于深入了解对象的内部结构以及进行高级编程操作非常重要。