「前端每日一问(2)」symbol 是什么? 解决了什么问题?

568 阅读2分钟

「这是我参与2022首次更文挑战的第30天,活动详情查看:2022首次更文挑战」。

本题难度:⭐

难度评级最高五星,最低一星

答:symbol 是 JS 在 ES6 时新增的特性,symbol是一个基本的数据类型,表示独一无二的值,用来防止对象属性名冲突问题。

概述

ES5 的对象属性名都是字符串,这容易造成属性名的冲突。比如,你使用了一个他人提供的对象,但又想为这个对象添加新的方法,新方法的名字就有可能与现有方法产生冲突。如果有一种机制,保证每个属性的名字都是独一无二的就好了,这样就从根本上防止属性名的冲突。这就是 ES6 引入Symbol的原因。

ES6 引入了一种新的原始数据类型Symbol,表示独一无二的值。它是 JavaScript 语言的第七种数据类型,前六种是:undefinednull、布尔值(Boolean)、字符串(String)、数值(Number)、对象(Object)。

Symbol 值通过Symbol函数生成。这就是说,对象的属性名现在可以有两种类型,一种是原来就有的字符串,另一种就是新增的 Symbol 类型。凡是属性名属于 Symbol 类型,就都是独一无二的,可以保证不会与其他属性名产生冲突。

基本使用

const symbol1 = Symbol()
const symbol2 = Symbol(42)
const symbol3 = Symbol('foo')

console.log(typeof symbol1)    // 'symbol'

console.log(symbol2 === 42)    // false

console.log(symbol3.toString()) // 'Symbol(foo)'

console.log(Symbol('foo') === Symbol('foo')) // false

尽管调用Symbol() 让它看起来像是对象,实际上symbol是 JavaScript 原始数据类型。把Symbol当作构造函数来用 new会报错。

new Symbol() // Uncaught TypeError: Symbol is not a constructor

防止对象属性名冲突

const obj = {
  name: 'lin',
  age: 18
}

obj.name = 'xxx'   // 给 obj.name 赋值,把以前的 name 覆盖了
console.log(obj) // { name: 'xxx', age: 18 }
const obj = {
  name: 'lin',
  age: 18
}
const name = Symbol('name')

obj[name] = 'xxx'   // 使用 Symbol,不会覆盖


console.log(obj)    // { name: 'lin', age: 18, Symbol(name): 'xxx' }
console.log(obj.name)  // 'lin'
console.log(obj[name]) // 'xxx'

更多相关知识可访问 mdn

这是阿林持续更文的第30天,输出洞见技术,再会~

上一篇:

「前端每日一问(1)」BigInt 是什么? 解决了什么问题?

下一篇:

「前端每日一问(3)」JS 原始类型和引用类型的区别?