JavaScript ES6 奇妙的Symbol类型(╹ڡ╹ )

在这里插入图片描述

JavaScript ES6 奇妙的Symbol类型


一、Symbol

Symbol 中文释义符号、象征,有时也被用来做变量名,在 ES6 中将其变为了一种基本数据类型。每个从 Symbol() 返回的 symbol 值都是唯一的,这就意味着symbol能做为对象属性的标识符,我想这也是将这种数据类型命名为 Symbol 的原因之一。

使用 Symbol 的基本语法为 Symbol([description])description 参数为对symbol的描述,可用于调试但不是访问symbol本身。

// 声明一个 symbol 类型
const demo = Symbol("demo")

// 每一个symbol都是唯一的,即使描述值相等
console.log(Symbol("demo") === Symbol("demo"))

二、Symbol类型判断与转换

  • 使用抽象(宽松)相等时,对象类型与 Symbol类型相等,字符串类型与 Symbol类型不相等。

    const demo = Symbol("demo");
    
    console.log(demo == Object(demo))
    // true
    console.log(demo == String(demo))
    // false
    
  • 将一个 Symbol 数据类型转换为一个 Number 值时,会抛出一个 TypeError 错误。

  • symbol会阻止隐式地创建一个新的 string 类型并抛出 TypeError 异常。

    const demo = Symbol("demo");
    
    console.log({"name": "张三"} + "罗翔")
    // [object Object]罗翔
    console.log(new Map([["name", "张三"]]) + "罗翔")
    // [object Map]罗翔
    console.log([1, 2, 3] + "罗翔")
    // 1,2,3罗翔
    console.log(demo + "bar")
    // 抛出 TypeError 异常
    
  • 将 Symbol 数据类型转换为字符串类型要分为两种,一种是直接的字符串转换,另外一种则是取出对symbol的描述值,也就是在创建 Symbol 数据类型时传入的参数,第二种使用更多些。

    直接转换

    const demo = Symbol("demo");
    
    console.log(demo.toString())
    // Symbol(demo)
    console.log(String(demo))
    // Symbol(demo)
    

    描述值提取

    const demo = Symbol("demo");
    console.log(demo.description)
    // demo
    

三、Symbol方法

1)、Symbol.for(key)

给定 key 搜索现有的 symbol,找到则返回上次存储的那个 symbol,否则根据key在 全局symbol注册表 中创建一个新的symbol对象。

const demo = Symbol.for("demo");
console.log(demo === Symbol.for("demo"))
// true
console.log(Symbol.for("demo") === Symbol.for("demo"))
// true
console.log(demo.toString())
//Symbol(demo)

Symbol() 不同的是,使用 Symbol.for() 方法创建的 symbol 会放入全局 symbol 注册表中,而 Symbol() 不会。
这就意味着使用 Symbol() 创建的 symbol 与使用 Symbol.for() 方法返回的不是同一个。

const sym = Symbol("hello");
const sym_f1 = Symbol.for("hello")
const sym_f2 = Symbol.for("hello")

console.log(sym === sym_f1)
// false
console.log(sym === sym_f2)
// false
console.log(sym_f1 === sym_f2)
// true
console.log(Symbol.keyFor(sym))
// undefined

2)、Symbol.keyFor(sym)

Symbol.for() 方法一样,Symbol.keyFor(sym) 方法也涉及到 全局symbol注册表Symbol.keyFor(sym) 方法用于获取全局 symbol 注册表中与某个 symbol 关联的键,Symbol() 所创建的 symbol 不能查找。

const sym = Symbol("hello");
const demo = Symbol.for("demo");

console.log(Symbol.keyFor(sym));
// undefined
console.log(Symbol.keyFor(demo));
// demo
{
    console.log(Symbol.keyFor(demo))
    // demo
}

四、Symbol原型

实例属性

1)、Symbol.prototype.description

只读属性,返回 Symbol 对象的描述的字符串

const sym = Symbol("hello");
console.log(sym.description)
// hello

实例方法

1)、Symbol.prototype.toString

返回当前 symbol 对象的字符串表示

// 直接拼接会抛出数据类型异常
Symbol("a") + "b";
// 直接拼接会抛出数据类型异常:TypeError: Can't convert symbol to string

Symbol("a").toString() + "b"
// "Symbol(a)b"

Object(Symbol("foo")).toString() + "bar"
// 使用对象中toString方法也是可以的:"Symbol(foo)bar"

注意:此方法重写了原型链上的 Object.prototype.toString() 方法

2)、Symbol.prototype.valueOf

返回当前 symbol 对象所包含的 symbol 原始值

const sym = Symbol("hello");
console.log(sym);
console.log(sym.valueOf());
console.log(sym === sym.valueOf());
Symbol(hello)
Symbol(hello)
true

五、Symbol简单的应用场景

1)、手撕函数调用方式 call、apply、bind
根据 Symbol 值都是不相等的特性,将其作为标识符,用于对象的属性名,保证不会出现同名的属性,有效防止某一个键被不小心改写或覆盖。

Function.prototype._call = function (fn, ...args) {
    // 声明临时变量
    const func = Symbol("func");
    // 将目标方法拷贝到this执行的对象上
    fn[func] = this;
    // 执行方法并获取返回结果
    const result = fn[func](...args);
    // 删除拷贝方法
    delete fn[func];
    // 返回结果
    return result;
}

const obj1 = {
    func: function (...args) {
        console.log(this.name)
        console.log(args)
    }
}

const obj2 = {
    name: "张三"
}
obj1.func._call(obj2, 1, 2, 3, 4, 5)
张三
[1, 2, 3, 4, 5]

2)、消除魔术字符串

魔术字符串指的是,在代码之中多次出现、与代码形成强耦合的某一个具体的字符串或者数值。风格良好的代码,应该尽量消除魔术字符串,改由含义清晰的变量代替。

使用 Symbol 类型是一个很好的方案。

const Tags = {
    hot: Symbol("hot"),
    news: Symbol("news"),
    likes: Symbol("likes")
}

function getTags(tab) {
    switch (tab) {
        case Tags.hot:
            return `<h1>热门</h1>`
        case Tags.news:
            return `<h1>最新</h1>`
        case Tags.likes:
            return `<h1>最受欢迎</h1>`
    }
}

document.write(getTags(Tags.hot))

参考资料💕


相关博客🍗

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值