ECMAScript 6 通过在 原型链 上定义与 Symbol 相关的属性来暴露语言内部逻辑,使得开发者可以对一些语言的默认行为做配置。接下来我们来看看有哪些重要的 Symbol 属性可供我们使用:
1: Symbol.hasInstance 一个在执行 instanceof 时调用的方法,用于检测对象的继承信息
2: Symbol.isConcatSpreadable 一个布尔值,用于表示当传递一个集合作为 Array.prototype.concat()的参数是,是否应该将集合内的元素拍平到同一层级
3: Symbol.iterator 在迭代器和生成器那篇文章已经细讲过
4: Symbol.match 一个在调用 String.prototype.match()时调用的方法,用于比较字符串
5: Symbol.replace 一个在调用 String.prototype.replace()时调用的方法,用于替换字符串的子串
6: Symbol.search 一个在调用 String.prototype.search()时调用的方法,用于定位子串在字符串中的位置
7: Symbol.split 一个在调用 String.prototype.split()时调用的方法,用于分割字符串
8: Symbol.species 用于创建派生对象的构造函数
9: Symbol.toPrimitive 一个返回对象原始值的方法
10: Symbol.toStringTag 一个在调用 Object.prototype.toString()时使用的字符换,用于创建对象的描述
11: Symbol.unscopables 一个定义了一些不可被 with 语句引用的对象属性名称的对象集合
上面的属性很多,这里会挑一些比较重要和常用的来讲:
1: Symbol.hasInstance
Symbol.hasInstance 用于确定对象是否为函数的实例。此方法定义在 Function.prototype 中,所以所有的函数都默认继承了此方法。当我们在调用例如
obj instanceof Array;
其实等价于:
Array[Symbol.instanceof](obj);
文章开头我们就说了这些 symbol 属性是为了开发者能定制化语言的内部逻辑,那我们怎样改写 Symbol.hasInstance 的默认行为呢?这里面有一点特殊的是,为了确保 Symbol.instance 不会被意外地重写,该方法是被默认定义为不可写,不可配置,和不可枚举。如果确定要改写它,必须通过 Object.definePropoty()方法:
function MyObject(){};
Object.defineProperty(MyObject, Symbol.hasInstance, {value: function () {return false;}
});
let obj = new MyObject();
console.log(obj instanceof MyObject); // false
以上代码,我们就重写了 Symbol.hasInstance 的默认逻辑,让它始终返回 false,所以哪怕明明 obj instanceof MyObject 逻辑上应该返回 true,但是结果得到 false。这个例子本身逻辑上没有意义,甚至是错误地,只是想要展示一下 Symbol.hasInstance 的用法。
我们还也可以让 Symbol.hasInstance 只是某些情况下返回 true,但是一定要保证 instanceof 的左边是一个对象,这样才能触发对 Symbol.hasInstance 的调用,不然 instanceof 总是返回 false。
2: Symbol.isConcatSpreadable
3: Symbol.match,Symbol.replace, Symbol.search,Symbol.split
4: Symbol.toPrimitive
5: Symbol.toStringTag