知名符号(公共、具名)是一些具有特殊含义的共享符号,通过Symbol的静态属性得到
ES6延续了ES5的思想:减少魔法,暴露内部实现!
因此ES6用知名符号暴露了某些场景的内部实现。
- Symbol.hasInstance
该符号用于定义构造函数的静态成员,它将影响instanceof的判定
obj instanceof A
//等效于
A[Symbol.hasInstance](obj) //Function.prototype[Symbol.hasInstance]
例:
function A() {
}
const obj = new A();
console.log(obj instanceof A); //true
console.log(A[Symbol.hasInstance](obj));//true
这里有了Symbol.hasInstance这个静态属性,我们便可以参与instanceof的判定的内部实现,这次为了让它判断的时候返回false。
function A() {
}
Object.defineProperty(A, Symbol.hasInstance, {
//这里甚至可以写一些打印的语句,在执行instanceof判断的时候也是会打印到控制台的。
value: function(obj) {
return false;
}
})
const obj = new A();
console.log(obj instanceof A); //false
console.log(A[Symbol.hasInstance](obj)); //false
- Symbol.isConcatSpreadable
该知名符号会影响数组concat 方法
const arr = [3];
const arr2 = [5, 6, 7, 8];
//arr2[Symbol.isConcatSpreadable] = false;
const result = arr.concat(3);
const result1 = arr.concat(56, arr2);
console.log(result);
console.log(result1);
这里的concat可以有两种可能的方式,一个是将数组arr2作为一个元素与arr数组连接组成result1另一个是将数组arr2展开作为多个元素与arr数组连接。这里arr2[Symbol.isConcatSpreadable] = false;concat就会以第一种方式不展开数组,而不写(默认为true)或指定arr2[Symbol.isConcatSpreadable] = true;则为第二种方式,将arr2展开。
这个静态方法还可以用于对象
const arr = [3];
const obj = {
0: 2,
1: 3,
length: 2,
// [Symbol.isConcatSpreadable]: true
}
const result1 = arr.concat(56, obj);
console.log(result1); // [3, 56, {…}] //(4) [3, 56, 2, 3]

默认情况,对象不会展开分割是作为一个元素连接到数组;如果在对象里加这样[Symbol.isConcatSpreadable]: true一个属性,就会将对象里有连续索引的项展开。
这里受到 length属性的影响,可以在控制台,多试几个情况体验它的特点。
3. Symbol.toPrimitive 该知名符号会影响类型转换的结果
const obj = {
a: 1,
b: 2
}
//obj[Symbol.toPrimitive] = function() {
return 2;
}
console.log(obj.valueOf()); //拿到对象的基本类型 {a: 1, b: 2}
console.log(obj.toString()); //[object Object]
console.log(obj + 123); //[object Object]123
console.log(obj * 123); //NaN
如果加上这一语句obj[Symbol.toPrimitive] = function(){ retrun 2;}控制台输出结果将会变成如下情形:
例2
class Temperature {
constructor(degree) {
this.degree = degree;
}
// [Symbol.toPrimitive](type) {
// console.log(type)
// if (type === "default") {
// return this.degree + "摄氏度";
// } else if (type === "number") {
// return this.degree;
// } else if (type === "string") {
// return this.degree + "℃"
// }
// }
}
const t = new Temperature(30);
console.log(t + "!"); //[object Object]!
console.log(t / 2); //NaN
console.log(String(t)); //[object Object]
这是一个温度的类,默认是调用valueOf()、toString类型转换输出。当给这个类添加了
[Symbol.toPrimitive](type) {
console.log(type)
if (type === "default") {
return this.degree + "摄氏度";
} else if (type === "number") {
return this.degree;
} else if (type === "string") {
return this.degree + "℃"
}
}
这样我们就可以干预到类型转换,输出结果如下:
4. Symbol.toStringTag 该知名符号会影响Object.prototype.toString 的返回值
class Person {
// [Symbol.toStringTag] = "Person"
}
const p = new Person();
const arr = [325, 35, 89];
console.log(p.toString());
console.log(arr.toString());
console.log(Object.prototype.toString.apply(p));
console.log(Object.prototype.toString.apply(arr));

这里arr.toString是Array底层更改了toString实现,要使用apply改变this指向运用Object.prototype.toString的方法,来验证结果。
当启用了[Symbol.toStringTag] = "Person"就会得到如下结果:

此处只列举了4 个还有其他知名符号,可以去学习。
这样我们就可以使用一些Symbol静态方法(知名符号),来参与JS的底层实现。
来源:CSDN
作者:weixin_45048106
链接:https://blog.csdn.net/weixin_45048106/article/details/104085805