创建
符号没有字面量形式。使用 Symbol 函数可以创建一个符号,这个函数接收可选的字符串,用于描述这个符号,这个字符串存储在内部属性 [[Description]] 中,调用符号的 toString()
方法时,该信息会被读取。使用 typeof 可以判断变量类型是否为符号类型。
let a = Symbol();
let b = Symbol("a symbol");
let obj = {};
obj[a] = "xyz";
obj[b] = "qwe";
console.log(obj[a]); // xyz
console.log(obj[b]); // qwe
console.log(b); // Symbol("a symbol")
console.log(typeof b); // symbol
使用
符号主要在对象中作为方括号里面计算的属性名使用。该类型属性不能使用 for-in 遍历,不会在 Object.keys()
结果中显示。
let s = Symbol();
let obj = {
[s] : "abc"
};
共享
如果在不同的文件或者对象中需要使用同一个符号,可以使用 Symbol.for()
函数实现。这个函数接收一个字符串,这个字符串将作为键去全局符号注册表查找是否存在对应的符号,如果存在,则返回这个符号;如果不存在,则创建对应的符号存入全局符号注册表同时返回该符号。
Symbol.keyFor()
方法接收一个符号,如果全局符号注册表中存在该符号,则返回这个符号对应的键;否则,返回 undefined。只有通过 Symbol.for()
创建的符号才存放在全局符号注册表中。
let id = Symbol.for("uid");
Symbol.keyFor(id); // "uid"
let ano = Symbol("uid");
Symbol.keyFor(ano); // undefined
符号值转换
符号在逻辑运算中等价于 true,符号不能转换成字符串或者数值类型的值。
检索符号属性
Object.keys()
方法返回对象可枚举的所有属性名称。
Object.getOwnPropertyNames()
方法返回对象除了符号类型的所有属性名称。
Object.getOwnPropertySymbols()
方法返回以对象的符号类型属性为元素构成的数组。
使用符号内部方法
js 定义的符号都对应全局 Symbol 对象的属性。
每个函数都有 Symbol.hasInstance()
方法,该方法接收一个参数,若参数是本函数的一个实例,则返回 true。instanceof 本质上调用了这个方法。
// 更改 Symbol.hasInstance 方法,使得所有对象都不是特定函数的实例
function Fun() {
// body
}
Object.defineProperty(Fun, Symbol.hasInstance, {
value: function(v) {
return false;
}
});
let f = new Fun();
f instanceof Fun; // false
Symbol.isConcatSpreadable 是布尔类型属性,用于表示对象使用或参与 concat()
方法时的行为。它为 true 时表示对象有长度属性、数值类型的键并且该类型键对应的值在参与 concat()
方法时分离为个体对待。
let obj = {
0: "a",
1: "b",
length: 2,
[Symbol.isConcatSpreadable]: true
};
let arr = ["z"].concat(obj); // ["z", "a", "b"]
Symbol.match()
接收一个字符串,返回包含匹配结果的数组或者返回 null。
Symbol.replace()
接收一个字符串和一个替换用字符串,返回替换后的字符串。
Symbol.search()
接收一个字符串,返回匹配结果的索引或者 -1。
Symbol.split()
接收一个字符串,返回用匹配值分割的字符串数组。
let obj = {
[Symbol.match]: function(v) {
return v.length == 3 ? [v.substring(0, 3)] : null;
},
[Symbol.replace]: function(v, sub) {
return v.length == 3 ? sub + v.substring(3) : v;
},
[Symbol.search]: function(v) {
return v.length == 3 ? 0 : -1;
},
[Symbol.split]: function(v) {
return v.length == 3 ? ["", ""] : [v];
}
};
let arr = "123",
str = "13";
arr.match(obj); // ["123"]
str.match(obj); // null
arr.replace(obj, "xyz"); // "xyz"
str.replace(obj, "xyz"); // "13"
arr.search(obj); // 0
str.search(obj); // -1
arr.split(obj); // ["", ""]
str.split(obj); // ["13"]
Symbol.toPrimitive()
方法规定了对象转换成基本类型值时具体发生的行为,该方法接收一个字符串,当字符串为 "number" 时,对象转换成数值;为 "string" 时,对象转换成字符串;为 "default" 时,转换不作特定要求。
页面中有内联帧 (iframe) 时,页面和内联帧分别具有不同的全局执行环境,将存在于一个全局环境中的对象传递到另一个全局环境时,这个对象在新的全局环境中类型不被识别。例如,将一个数组从一个全局环境传递到另一个中,使用 instanceof Array 返回 false,由于不同全局环境的数组构造器不一致。
Object.prototype 上的 toString()
方法返回值中会包含 [[Class]] 内部属性中的值,不同全局执行环境中创建的相同类型对象使用该方法,返回值相同。对象在不同全局执行环境中传递之后可以使用该方法判断对象的类型。调用形式为 Object.prototype.toString.call(obj)
。
Symbol.toStringTag 内部属性定义了对象调用 Object.prototype.toString.call()
方法返回的值。可以在自定义对象中定义该属性的值,该属性定义在 prototype 中。
Symbol.unscopables 是一个对象属性,在 Array.prototype 上使用,它的键对应的值如果为 true 表示该键表示的标识符在 with 语句中不能被绑定。
参考
[1] Zakas, Understanding ECMAScript 6, 2017.
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix