那些小而美的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);     // 返回"这是一个陌生的属性"
相关推荐
Dovis(誓平步青云)5 分钟前
拖动关键帧角色就抽动,动画编辑器怎样补齐中间状态
开发语言·前端·javascript·机器学习·编辑器
lpfasd12313 分钟前
pywebview与Electron
前端·javascript·electron
行走的陀螺仪20 分钟前
Claude Code 从入门到实战(一):安装、登录与第一个Vue项目
前端·javascript·vue.js
vipxieliang31 分钟前
解构赋值与展开运算符:现代 JS 提效技巧
javascript
2603_965896621 小时前
JavaScript 原型与原型链
开发语言·前端·javascript
晓得迷路了1 小时前
栗子前端技术周刊第 152 期 - Rspack 2.3、TypeScript 7.1 Beta、Bun 1.4.4...
前端·javascript·css
ZhengEnCi2 小时前
面试官为什么总问底层原理:你不是不如他,而是他被「筛选器」困住了
面试·程序员·求职
苏三的开发日记2 小时前
MySQL InnoDB 与 Spring Boot 事务机制
面试
jktantan11 小时前
Vue keep-alive 切标签后滚动位置回顶?因为 onDeactivated 里读到的 scrollTop 是 0
前端·javascript·vue.js
总要学点什么11 小时前
第89篇:三维特效-螺旋圆效果——让螺旋臂卷起一圈圈外扩的涟漪
开发语言·javascript·ecmascript·webgl·cesium·空间分析·1024程序员节