- Symbol.hasInstance
The Symbol.hasInstance
well-known symbol is used to check if an object constructor recognizes an object as its instance. The instanceof
operator’s behavior can be customized by this symbol.
operator
class ArrayA {
static [Symbol.hasInstance] (o) {
return Object.prototype.toString.call(o)
}
}
[] instanceof ArrayA // true, 相当于执行下句
ArrayA[Symbol.hasInstance]([]) // true
- Symbol.iterator
The Symbol.iterator
specifics the default iterator
of an object. Used by for ... of
.
let o = {}
o[Symbol.iterator] = function* () {
yield 1
yield 2
yield 3
}
console.log([...o]) // [1, 2, 3]
for (let v of o) {
console.log(v)
}
// 1, 2, 3
let s1 = 'this'
s1['a'] = 0
// 在值类型(primitive type)变量上添加属性无效
Object.getOwnPropertyNames(s1)
// ['0', '1', '2', '3', 'length']
s1['a'] // undefined
function* gen() = {yield* [1, 2, 3]}
s1[Symbol.iterator] = () => gen()
// 仍然是调用的String.prototype[Symbol.iterator]
[...s1] // ['t', 'h', 'i', 's']
s1[Symbol.iterator] // [Function: [Symbol.iterator]]
let s2 = new String('this')
s2 = () => gen()
[...s2] // [1, 2, 3]
- Symbol.toStringTag
The Symbol.toStringTag
well-known symbol specifics a string valued property in the creation of string description of an object. It is accessed internally by the Object.prototype.toString()
method.
let toStringTag = function(o) {
return Object.prototype.toString.call(o)
}
// 基本数据类型
toStringTag(1) // '[object Number]'
toStringTag(true) // '[object Boolean]'
// 内建数据结构,GeneratorFunction/RegExp/Array/Map等
toStringTag(function(){}) // '[object Function]'
toStringTag(Promise.resolve(1)) // '[object Promise]'
toStringTag(new Set()) // '[object Set]'
// 新建类
class ClassA {}
class ClassB {
// 一个getter
get [Symbol.toStringTag] () { return 'B' }
}
toStringTag(new ClassA()) // '[object Object]', 默认
toStringTag(new ClassB()) // '[object B]', 仍然有前面的object
- Symbol.match
The Symbol.match
well-known symbol specifics the matching of a regular expression against a string. The function is called by the String.prototype.match()
method.
let r = /is/
let s = 'this is a test.'
let arr = s.match(r) // ['is', index: 2, input: 'this is a test.']
r[Symbol.match](s) // 同上句
arr instanceof Array // true, 返回数组
for (let k in arr) {
console.log(k, arr[k])
}
// 0 'is', index 2, input: '...'
/is/g[Symbol.match](s) // ['is', 'is']
s.match(/abc/) // null, 注意不是[]和undefined
The subclass of RegExp
can override the [@@match]()
method to modify the default behavior.
class RegExpA extends RegExp {
[Symbol.match] (str) { return 1 }
}
'this'.match(new RegExpA(/is/)) // 1, 始终返回1
The function is also used to identify if an object has behavior of regular expression. For example, the methods String.prototype.startsWith()
, String.prototype.endsWith()
and String.prototype.includes()
check if the first argument is a regular expression object, and will throw a TypeError if they are. Now, if the match
symbol is set to false (or a falsy value), it indicates that the object is not intended to be used as a regular expression object.
let r = /is/
let s = 'th/is/'
s.includes(r)
// TypeError:First argument to String.prototype.includes
// must not be a regular expression.
r[Symbol.match] = false // 或其他falsy(0, '', undefined, null, ...)
s.includes(r) // true
- Symbol.search Symbol.replace Symbol.split
class MyClass {
constructor (val) {
this.val = val
}
[Symbol.search] (str) {
return this.val + str[0]
}
[Symbol.replace] (str) {
return this.val + str[1]
}
[Symbol.split] (str) {
return this.val + str[2]
}
}
let s1 = 'this'
let s2 = new MyClass('is')
// Object.prototype的方法默认调用MyClass.prototype上对应的symbol
s1.search(s2) // ist
s1.replace(s2) // ish
s1.split(s2) // isi
- Symbol.toPrimitive
The Symbol.toPrivitive
well-known symbol specifics a funcion valued property that is called to convert an object to a corresponding primitive value.
let o = {}
console.log(+o, `${o}`, o + '', o + 1)
// NaN, '[object Object]', '[object Object]', '[object Object]1'
o[Symbol.toPrimitive] = function(hint) {
if (hint == 'number') return 1
if (hint == 'string') return 's'
return 'o'
}
console.log(+o, `${o}`, o + '', o + 1)
// 1, 's', 'o', 'o1'
- Symbol.isConcatSpreadable
The Symbol.isConcatSepreadable
well-known symbol is used to config if an object should be flattened to its array elements when using the Array.prototype.concat()
method.
let arr1 = [1, 2, 3]
let arr2 = [4, 5]
let fakeArr = {
'0': 4,
'1': 5,
length: 2
}
arr1.concat[arr2] // [1, 2, 3, 4, 5]
arr1.concat[fakeArray] // [1, 2, 3, {...}]
arr2[Symbol.isConcatSpreadable] = false
o[Symbol.isConcatSpreadable] = true
arr1.concat[arr2]
// [1, 2, 3, [4, 5, [Symbol.isConcatSpreadable]: false]]
arr1.concat[fakeArray] // [1, 2, 3, 4, 5]
- Symbol.species
The Symbol.species
well-known symbol specifics a function-value property that the constructor function uses to create the derived objects.
class ArrayA extends Array {}
class ArrayB extends Array {
static get [Symbol.species] () { return Array }
}
let a = new ArrayA(...[1, 2, 3])
let b = new ArrayB(...[1, 2, 3])
let mapA = a.map(val => val)
let sliceA = a.slice()
let mapB = b.map(val => val)
let slcieB = b.slice()
a instanceof Array // true
a instanceof ArrayA // true
mapA instanceof ArrayA // true
sliceA instanceof ArrayA // true
b instanceof Array // true
b instanceof ArrayB // true
mapB instanceof Array // true
mapB instanceof ArrayB // false,衍生对象不是ArrayB的实例
slice instanceof Array // true
sliceB instanceof ArrayB // false,衍生对象不是ArrayB的实例
- Symbol.unscopables
// with相关
参考:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol