65.9K
CodeProject 正在变化。 阅读更多。
Home

JavaScript Symbols 基础知识

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.94/5 (8投票s)

2020 年 7 月 31 日

CPOL

5分钟阅读

viewsIcon

6642

JavaScript Symbol 类型简介

引言

截至本文撰写之时,Symbol 是最新的 JavaScript 原始类型。事实上,许多开发者(包括我最初)都不知道这个功能的存在。为一门语言引入新功能意味着为该语言带来好处,我们应该理解某个特定功能的具体用途。因此,我们将探讨 JavaScript Symbols 的好处及其特定用途。好了,我们开始吧。

目录

什么是 JavaScript Symbol?

JavaScript Symbol 是 ES6 中引入的一种新的原始类型。此外,Symbol 是一种唯一且不可变的值。创建新的 Symbol 非常简单,只需调用 `Symbol()` 函数即可,该函数每次调用时都会返回一个唯一的 Symbol。稍后将在示例中详细介绍。

JavaScript Symbol 的好处和用法?

创建新的 JavaScript Symbol 总是唯一的

正如我们在上一节中所描述的,我们说过,为了创建一个新的 JavaScript Symbol,我们只需要调用 `Symbol` 函数。关于它的另一件事需要提到,Symbol 没有字面量形式;因此,我们只能使用 `Symbol()` 函数来创建一个。

请看下面的示例。

//how to create a Symbol 

const mySymbol1 = Symbol();
const mySymbol2 = Symbol();

console.log(mySymbol1, mySymbol2);
//output: Symbol() Symbol()

带描述的 JavaScript Symbol,主要用于调试

现在,我们已经看到了如何创建一个新的 JavaScript Symbol。不要忘记,`Symbol()` 函数接受一个可选的字符串参数,该参数代表 `Symbol` 的描述。根据我的经验,描述用于调试目的,而不是用于访问 `Symbol` 本身。

请看下面的示例

//* how to create a Symbol with description

const mySymbolWithDescription1 = Symbol("First description");
const mySymbolWithDescription2 = Symbol("Second description");

console.log(mySymbolWithDescription1, mySymbolWithDescription2);
//output: Symbol(First description) Symbol(Second description)

具有相同描述的 JavaScript Symbol 不相等

Symbol 总是 100% 保证是唯一的。请记住,描述只是一个 `标签`,不会影响任何事情。再说一遍,描述只是一个 `标签`,仅此而已。

请看下面的示例

//Symbol with same description aren't equal 

const mySymbol_1 = Symbol("Cat");
const mySymbol_2 = Symbol("Cat");

console.dir(mySymbol_1 === mySymbol_2);
//output: false

调用新实例时使用 Symbol() 函数

我第一次学习 JavaScript Symbol 时,以为可以使用 `Symbol()` 函数创建一个新实例。结果,它抛出了一个错误,说:`“Symbol is not a constructor”`(Symbol 不是构造函数),在创建新实例时。

请看下面的示例

//how not to create a Symbol

try {
    const _newSymbols = new Symbol();
} catch (error) {
    console.dir(error.message);   //output: Symbol is not a constructor
}

所以,正如你在上面的例子中所看到的,使用 new 关键字来创建一个 `Symbol` 的新实例是行不通的,因为根据我们之前的章节,我们必须直接调用 `Symbol()` 函数。

JavaScript Symbol 类型及其转换为字符串

使用 `typeof` 运算符一直很有趣。因此,结果将是 `symbol` 而不是 `object`,因为它是一种原始类型。

根据我的观察,JavaScript 类型支持隐式转换为 `string`。然而,`Symbol` 类型不会自动转换。你确实需要显式调用 `.toString()` 方法。

使用 typeof 运算符检查类型

//Let's check if the type name of Symbol 
const mySymbolType = Symbol();

console.log(typeof mySymbolType);
//output: symbol   

在 alert 函数中调用 Symbol 类型

const mySymbolType = Symbol();

alert(mySymbolType);
//output: Uncaught TypeError: Cannot convert a Symbol value to a string

显式使用 .toString() 和 description 属性

const _newSymbols2 = Symbol("Hello");
console.log(_newSymbols2.toString());  //output: Symbol(Hello)
console.log(_newSymbols2.description); //output: Hello

将 JavaScript Symbol 用作对象键

截至今天,JavaScript 对象属性键可以是字符串或 Symbol。此外,拥有 `Symbol` 类型属性的对象在尝试枚举对象键时不会被列出。因此,在我看来,当您枚举时它看起来是隐藏的,但当您使用 `[]` 令牌时并非如此。

请看下面的示例

const customerSymbol = Symbol("Object date created");

let customer = {
    name: "Jin Vincent Necesario",
    [customerSymbol]: new Date()
};

console.log(customer); 

输出

我们尝试使用 for-in 循环进行枚举

for (const key in customer) {
    if (customer.hasOwnProperty(key)) {
        console.log(`customer.${key} is equals to ${customer[key]}`);
    }
}
//output: customer.name is equals to Jin Vincent Necesario
//Note: The symbol-key didn't appear to be part of the object

直接访问 Symbol 属性

但是,我们可以通过 `[]` 令牌访问包含 Symbol 的内容。

console.log("customer[customerSymbol] is equals to " + customer[customerSymbol].getFullYear());
//output: customer[customerSymbol] is equals to 2020

但是,当然,还有另一种方法可以直接通过使用 `Object.getOwnPropertySymbols()` 方法来访问 Symbol。

console.log(Object.getOwnPropertySymbols(customer));

输出

Symbol.for 方法

基本上,`Symbol` 对象维护一个键/值的注册表,其中键是描述,值是 Symbol。现在,当使用 `Symbol.for` 方法时,它会被添加到注册表中,并且该方法会返回 Symbol。因此,如果我们尝试创建一个具有现有描述的 Symbol,它将被检索。

//create a symbol using for method
const mySymbolFor = Symbol.for("My Unique Description");

let product = {
    name: "Toyota",
    [mySymbolFor]: "Toyota Hilux G"
};

const mySymbolFor2 = Symbol.for("My Unique Description");

console.log(mySymbolFor === mySymbolFor2); //output:true    

防止属性名冲突

现在,你已经走到了这一步。你可能已经在实际使用 JavaScript Symbol 了。你可能在想:“有什么好处?”

实际上,它们在库希望向对象添加属性而没有名称冲突风险的情况下很有用。

摘要

  • 当你尝试使用新实例时,Symbol 是使用 `Symbol()` 函数调用的,否则将抛出错误。
  • JavaScript Symbols 始终是唯一的。
  • Symbol 的描述专门用于调试,具有相同描述并不意味着 Symbol 是等价的。
  • 如果你想将 JavaScript Symbols 转换为 `string`,则需要显式转换。
  • JavaScript Symbols 可用于对象属性中,以防止属性名称冲突。
  • `Symbol.for` 具有用于键值对的表注册,它会检索现有的 Symbol 描述,否则会创建一个新的。

希望您喜欢这篇文章,就像我喜欢写它一样。请继续关注更多内容。下次再见,祝您编程愉快!

历史

  • 2020 年 7 月 31 日:初始版本
© . All rights reserved.