十、Symbol数据类型
大约 4 分钟约 1073 字
(一)Symbol 简介
- JS 的第七种数据类型,表示独一无二的值
Symbol
值唯一,用于解决命名冲突的问题Symbol
值不能与其他数据进行运算【四则运算、字符串拼接、大小比较等】Symbol
定义的对象属性不能使用for...in
循环遍历,但是可以使用Reflect.ownKeys
来获取对象的所有键名
- JS 所有数据类型:USONB => you are so nubility
- U:
undefined
- S:
string
、symbol
- O:
object
- N:
null
、number
- B:
boolean
- U:
1.创建 Symbol
- 内部实现了唯一性,外部不可见
Symbol
是一个函数对象
1)方式一:Symbol 是一个函数
Symbol()
let s = Symbol();
console.log(s, typeof s);
// Symbol() 'symbol'
2)方式二:Symbol 是一个函数
- 传入一个描述性字符串,用于区分所定义的
Symbol
变量 - 标注当前
Symbol
变量的作用/意义,只是一个标志但是返回结果不同
let s2 = Symbol("ikuko");
let s3 = Symbol("ikuko");
console.log(s2 === s3);
// false
3)方式三:Symbol 是一个对象
- 通过
.for()
创建的Symbol
对象 - 可以通过传入的字符串得出唯一的
Symbol
值
let s4 = Symbol.for("ikuko");
console.log(s4, typeof s4);
// Symbol(ikuko) 'symbol'
let s5 = Symbol.for("ikuko");
let s6 = Symbol.for("yg");
console.log(s4 === s5, s4 === s6);
// true false
2.Symbol 不能与其他数据进行运算
let r1 = s + 100;
let r2 = s > 100;
let r3 = s + "100";
let r4 = s + s;
// Cannot convert a Symbol value to a number
(二)Symbol 创建对象属性
- 使用
Symbol
给对象添加属性或方法,确保独一无二
// 向对象中添加方法 up down
// 该对象结构较复杂,无法判断对象内部是否已经有up或down方法
let game = {
name: "2048",
up() {
console.log("自带的up方法");
},
down() {
console.log("自带的down方法");
},
};
// 以下写法有风险:如果对象内部有同名方法,会造成冲突
game.up = function () {};
game.down = function () {};
1.方式一:声明一个对象
let methods = {
up: Symbol(),
down: Symbol(),
};
game[methods.up] = function () {
console.log("我可以改变形状。");
};
game[methods.down] = function () {
console.log("我可以快速下降。");
};
console.log(game);
// {name: '2048', up: ƒ, down: ƒ, Symbol(): ƒ, Symbol(): ƒ}
2.方式二:使用 Symbol
let youxi = {
name: "狼人杀",
// Symbol(): function() {}
// 报错,因为【Symbol()不是一个固定属性,是动态值,是一个表达式】
// [Symbol()]: function(){}
[Symbol("say")]: function () {
console.log("我可以发言。");
},
[Symbol("zibao")]: function () {
console.log("我可以自爆。");
},
};
console.log(youxi);
// {name: '狼人杀', Symbol(say): ƒ, Symbol(zibao): ƒ}
(三)Symbol 内置值
ES6
可以定义自己使用的Symbol
值- 还提供了 11 个内置的
Symbol
值 - 指向语言内部使用的方法
- 还提供了 11 个内置的
- Symbol 内置值:
Symbol.XXX
- 其中
XXX
就是Symbol
对象的属性 Symbol.XXX
整体又作为Symbol
声明的对象的属性- 使用内置值可以改变
Symbol
对象在特定场景下的表现结果,扩展对象功能
- 其中
- 这些内置值都是在特定场景下自动触发的,不需手动调用
- 如使用
concat
时自动调用Symbol.isConcatSpreadable
- 如使用
内置值 | 说明 |
---|---|
Symbol.hasInstance | 其他对象使用 instanceof 运算符时,判断是否为该对象的实例 |
Symbol.isConcatSpreadable | 该对象用于 Array.prototype.concat() 时,是否可以展开 |
Symbol.unscopables | 使用 with 关键字时,哪些属性被 with 环境排除 |
Symbol.match | 使用 str.match(obj) 时,如果 obj 属性存在则调用,并返回该方法的返回值 |
Symbol.replace | 对象被 str.replace(obj) 调用时,返回该方法的返回值 |
Symbol.search | 对象被 str.search(obj) 调用时,返回该方法的返回值 |
Symbol.split | 对象被 str.split(obj) 调用时,返回该方法的返回值 |
Symbol.iterator | 对象进行 for...of 循环时,返回该对象的默认遍历器 |
Symbol.toPrimitive | 对象被转为原始类型值时,返回该对象对应的原始类型值 |
Symbol.toStringTag | 对象调用 toString 时,返回该方法的返回值 |
Symbol.species | 创建衍生对象时使用该属性 |
1.Symbol.hasInstance
- 自定义类型检测的参数、返回结果
class Person {
static [Symbol.hasInstance](param) {
console.log(param); // "instanceof"关键字前面的变量
console.log("我被用来检测类型了");
return true; // 缺省则返回false
}
}
let o = {};
console.log(o instanceof Person);
// {}
// 我被用来检测类型了
// true
2.Symbol.isConcatSpreadable
- 控制当前 Symbol 值是否可以展开拼接
const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
console.log(arr1.concat(arr2));
// [1, 2, 3, 4, 5, 6]
arr2[Symbol.isConcatSpreadable] = false;
console.log(arr1.concat(arr2));
// [1, 2, 3, Array(3)]