那些小而美的JS基础知识 - Symbol

最近在恶补JS基础,正好看到了Symbol这块,所以决定记录一下。

阅读了阮一峰老师的es6教程,现总结如下:

一、它是用来干什么的?

我们都知道对象的属性名都是字符串,这就很容易造成属性名字的冲突,导致原有的固有方法被重写(这也叫做mixin混入模式)。

这个时候就需要一种机制,来保证每个属性名字都是独一无二的。Symbol就是这种机制。

二、用法

javascript 复制代码
let a = symbol(); 
let b = symbol("foo"); 
let c = symbol("bar");

我们可以看到,symbol函数里面,参数是可有可无的。参数的作用仅仅是对当前symbol值的描述。

三、特点

  • symbol可以转化为字符串、布尔值;转化为其他类型均报错。
  • symbol不能参与计算。
  • 因为symbol值是独一无二的,所以,即使描述符相同的2个symbol值是不相等的。
  • symbol值作为属性名字时,不能使用点运算符来得到该属性,而是使用方括号的形式来get or set。因为点运算符后面总是跟着字符串。
  • symbol类型的对象属性名字,不能被 Object.keys、Object.getOwnPropertyNames、for...in...、for...of... 遍历到。

代码实践

javascript 复制代码
let b1 = 'b1';

let obj1 = {
    a: 11,
    b: 22,
    [Symbol('sty')]: 55,
    [b1]: 66
}

obj1.__proto__ = {
    c: 33
}

Object.keys(obj1);                  // 【"a","b","b1"】

Object.getOwnPropertyNames(obj1);   // 【"a","b","c1"】

Object.getOwnPropertySymbols(obj1); // 【Symbol(sty)】

四、内置的symbol类型的属性名

  • Symbol.hasInstance。
  • Symbol.isConcatSpreadable。
  • Symbol.iterator。
  • Symbol.toPrimitive。
  • Symbol.toStringTag。

4.1、Symbol.hasInstance

指向了 instanceOf 的秘密。当我们使用 instanceOf 来检测某某实例时,实际上就是调用的这个方法。

javascript 复制代码
foo instanceOf Foo;   // 等价于下面的写法

Foo[Symbol.hasInstance](foo);

4.2、Symbol.isConcatSpreadable

表示该对象是否可被array.concat方法展开。当此属性值为true时,表示此对象可以被展开。

javascript 复制代码
let arr1 = [1, 2];
arr1[Symbol.isConcatSpreadable] = false;
[].concat(arr1);   // 返回:【 【1, 2】 】

let arr2 = { length: 3, 0: 'a', 1: 'b', 2: 'c' };
arr2[Symbol.isConcatSpreadable] = true;
[].concat(arr2);   // 返回: [ 'a', 'b', 'c' ]

4.3、Symbol.iterator

当一个数据结构拥有了Symbol.iterator属性,那么它就可以与for ... of ... 一起使用。反之亦然。

4.4、Symbol.toPrimitive

这个方法是干啥的呢?

在这个内置的Symbol属性(Symbol.toPrimitive)的作用下,对象可以转换为一个原始值。

当发生强制类型转换的时候,会自动调用这个方法,这个方法接受一个字符串参数,并且值只能是"string"、"number"、"default"。

javascript 复制代码
let obj = { 
    a: 22,
    [Symbol.toPrimitive](hint){
        switch(hint){
           case 'number':
                return 100;
           case 'string':
                return '200';
           case 'default':
                return 'default';
           default:
                throw new Error('something is wrong');
        }
    }
};

obj1 == 'default';      // true

(2 * obj1) === 200;     // true

4.5、Symbol.toStringTag

我们知道,JS中提供了多种数据类型检测的方法,其中Object.prototype.toString.call这个方法屡试不爽。

原因很简单,相对来说,它是万能油。

typeof 不能检测数组跟null类型;Array.isArray只能用来检测数组;instanceOf只能用来检测引用数据类型。

那么Object.prototype.toString.call方法是如何实现的呢?

答案就是这个内置的Symbol属性。

javascript 复制代码
let obj = {
    [Symbol.toStringTag]: "这是一个陌生的属性"
}

Object.prototype.toString.call(obj);     // 返回"这是一个陌生的属性"
相关推荐
Mr Xu_28 分钟前
从后端数据到前端图表:深入解析 reduce 与 flatMap 的数据整形实战
前端·javascript
喜欢吃鱿鱼2 小时前
DES加解密(附带解决转义问题)-VUE
开发语言·前端·javascript
愚者游世2 小时前
variadic templates(可变参数模板)各版本异同
开发语言·c++·程序人生·面试
忆往wu前2 小时前
一文通透 Vue动态组件体系:插槽|数据监听|组件通信|动态切换|缓存—闭环
前端·面试
Jenlybein2 小时前
速学 VS Code 插件开发入门,客制化你的开发体验
前端·javascript·visual studio code
Cosolar2 小时前
大模型应用开发工程师 · 学习路线(完整技术栈版)
人工智能·面试·架构
haina20192 小时前
海纳AI正式发布“面试Agent”——实现千岗千面与人机共管的智面新纪元
人工智能·面试·职场和发展
ZC跨境爬虫3 小时前
UI前端美化技能提升日志day7:(原生苹方字体全局适配+合规页脚完整像素级落地)
前端·javascript·ui·html·交互
好运的阿财3 小时前
OpenClaw工具拆解之tts+web_search
前端·javascript·python·ai·ai编程·openclaw·openclaw工具
兩尛3 小时前
c++面试常问1
jvm·c++·面试