2023-03-08 ES6之特殊类型Symbol

38 阅读2分钟

引入Symbol的原因

由于ES5中对象的属性名都是字符串,容易造成属性名的重名冲突,所以ES6引入独一无二的Symbol值防止属性名冲突

Symbol的两种创建方法

1. Symbol()函数

使用Symbol()函数创建的值不会有重复,每一个都是独一无二的,其类型是symbol

const s1 = Symbol();
console.log(typeof s1); // symbol

Symbol()函数也可以接收字符串参数,作为Symbol实例的描述,但是两个同名的还是独一无二的值

let s2 = Symbol("xx");
let s3 = Symbol("xx");

console.log(s2 === s3); // false

2. Symbol.for()函数

使用Symbol.for()函数创建的会首先在全局命名空间里寻找指定参数的值,没有则创建一个,有则返回 注意:这里Symbol.for()里的参数必须传

let s4 = Symbol.for("xiaoxu");
let s5 = Symbol.for("xiaoxu");

console.log(s4 === s5); // true

注意:Symbol值不能与其他类型的值进行运算,会报错;但是Symbol值可以显示的转为字符串

Symbol创建对象属性

第一种,用方括号[Symbol()]来表示对象的属性名

第二种,用Object.defineProperty(object, Symbol(), {value})方法来创建

注意:Symbol值作为对象属性时,不能用点运算符

Symbol属性名的遍历

当Symbol值作为属性名,遍历对象的时候,该属性不会出现在for...infor...of循环遍历中

也不会被Object.keys()Object.getOwnPropertyNames()JSON.stringify()等返回

只能通过Object.getOwnPropertySymbols()方法获取指定对象的所有Symbol属性名,或者Reflect.ownKeys()方法返回所有类型的属性名,包括常规键名和Symbol键名

Symbol的内置属性

Symbol内置属性太多,简单举两个例子

第一个:Symbol.hasInstance:执行intanceof时触发

class Person {
  static [Symbol.hasInstance](params) {
    console.log(params);
    console.log("我用来检测类型了");
    return false;
  }
}

const p = {
  name: "p"
};

console.log(p instanceof Person); // 输出log

第二个:Symbol.isConcatSpreadable:是否展开,执行concat时触发

const arr = [1, 2, 3];
const arr2 = [4, 5, 6];
arr2[Symbol.isConcatSpreadable] = false;
console.log(arr.concat(arr2)); // [1,2,3,[4,5,6]]