前端那些事

vuePress-theme-reco chenpeng    2020 - 2021
前端那些事 前端那些事

Choose mode

  • dark
  • auto
  • light
首页
文章目录
  • Browser
  • CSS
  • ES6
  • JavaScript
  • Network
  • TypeScript
  • Vue
  • Vue3
  • Webpack
标签
时间轴
GitHub
author-avatar

chenpeng

85

Article

25

Tag

首页
文章目录
  • Browser
  • CSS
  • ES6
  • JavaScript
  • Network
  • TypeScript
  • Vue
  • Vue3
  • Webpack
标签
时间轴
GitHub
  • ES6-基础

    • let、const 和 var的概念与区别
    • 对象的解构赋值
    • Symbol概念及其作用
    • Iterator 和 for..of
    • 循环语法比较及使用场景(for、forEach、for...in、for...of)

Symbol概念及其作用

vuePress-theme-reco chenpeng    2020 - 2021

Symbol概念及其作用

chenpeng 2020-11-30 ES6基础

# 1.概念

ES6 引入了一种新的原始数据类型 Symbol,表示独一无二的值,给对象添加属性或方法。它是 JavaScript 的第七种数据类型,是一种类似于字符串的数据类型

Symbol 值通过 Symbol 函数生成,注意 Symbol 函数前不能使用 new 命令,否则会报错。这是因为生成的 Symbol 是一个原始类型的值,不是对象。也就是说,由于 Symbol 值不是对象,所以不能添加属性。基本上,它是一种类似于字符串的数据类型。

Symbol 函数可以接受一个字符串作为参数,表示对 Symbol 实例的描述,主要是为了在控制台显示,或者转为字符串时,比较容易区分。

let s1 = Symbol('foo');
let s2 = Symbol('bar');

s1 // Symbol(foo)
s2 // Symbol(bar)

s1.toString() // "Symbol(foo)"
s2.toString() // "Symbol(bar)"
1
2
3
4
5
6
7
8

如果 Symbol 的参数是一个对象,就会调用该对象的toString方法,将其转为字符串,然后才生成一个 Symbol 值。

const obj = {
  toString() {
    return 'abc';
  }
};
const sym = Symbol(obj);
sym // Symbol(abc)
1
2
3
4
5
6
7

Symbol函数的参数只是表示对当前 Symbol 值的描述,因此相同参数的Symbol函数的返回值是不相等的。

// 没有参数的情况
let s1 = Symbol();
let s2 = Symbol();

s1 === s2 // false

// 有参数的情况
let s1 = Symbol('foo');
let s2 = Symbol('foo');

s1 === s2 // false
1
2
3
4
5
6
7
8
9
10
11

Symbol 值可以转为字符串和布尔值,但是不能转为数值

let sym = Symbol('My symbol');

String(sym) // 'Symbol(My symbol)'
sym.toString() // 'Symbol(My symbol)'
1
2
3
4
let sym = Symbol();
Boolean(sym) // true
!sym  // false

if (sym) {
  // ...
}

Number(sym) // TypeError
sym + 2 // TypeError
1
2
3
4
5
6
7
8
9
10

# 2.作用

# 2.1 使用 Symbol 值作为对象属性名(key)

使用 Symbol 值作为对象的属性名,可以保证不会出现同名的属性。Symbol 值必须放在方括号之中,取值时也必须通过方括号来取值(因为点运算符后面是字符串,不会读取 Symbol 值作为标识名所指代的值)

const name = Symbol();
let obj = {
    [name]: '张三',
    age: 20
};
console.log(obj); // {age: 20, Symbol(): "张三"}
1
2
3
4
5
6

Symbol 类型的 key 不能通过 Object.keys() 或 for...in 来枚举,可以使用 Object.getOwnPropertySymbols() 来获取 Symbol 类型的属性名,也可以使用 Reflect.ownKeys() 来获取对象的所有属性名

Object.getOwnPropertySymbols(obj);

Reflect.ownKeys(obj).forEach(item => {
    console.log(obj[item]);
})
// 20
// 张三
1
2
3
4
5
6
7

# 2.2 使用 Symbol 代替常量,保证常量的值是唯一的

const log = {};

log.levels = {
  DEBUG: Symbol('debug'),
  INFO: Symbol('info'),
  WARN: Symbol('warn')
};
console.log(log.levels.DEBUG, 'debug message');
console.log(log.levels.INFO, 'info message');
1
2
3
4
5
6
7
8
9

# 2.3 使用 Symbol 定义类的非私有属性或方法

由于以 Symbol 值作为键名,不会被常规方法遍历得到。我们可以利用这个特性,为对象定义一些非私有的、但又希望只用于内部的方法。

const _name = Symbol();
class Person{
    constructor(name) {
        this[_name] = name;
    }
    getName(){
        console.log(this[_name]);
    }
}
1
2
3
4
5
6
7
8
9