我先发个测试类吧,也有一些注释,如果有有问题的地方请指出,有看不懂的可以一起探讨
然后,我也多去看看,多去整理下symbol类型在实际应用时的应用场景。
/**
* 测试symbol.asyncIterator
* 这个符号表示异步迭代器API函数
*/
export function symbolAsyncIterator () {
class Foo {
constructor (max) {
this.max = max
this.asyncIdx = 0
}
// yield* 是表达式,用于委托给另一个generator 或可迭代对象。
// 测试next()
* nextTT () {
while (this.asyncIdx < this.max) {
yield this.asyncIdx
this.asyncIdx++
}
}
async * [Symbol.asyncIterator] () {
while (this.asyncIdx < this.max) {
yield new Promise((resolve) => {
resolve(this.asyncIdx++)
})
}
}
}
async function asyncCount () {
let f = new Foo(5)
for (let index = 0; index < 5; index++) {
console.log(f.nextTT().next())
}
for await (const x of f) {
console.log(x)
}
}
asyncCount()
}
/**
* 有一些问题,在new 子类的时候报错TypeError: Cannot call a class as a function
* 该方法决定一个构造器对象是否认可一个对象是它的实例。Symbol.hasInstance
*/
export function symbolHasInstance () {
class Fooc {}
class FoocSun extends Fooc {
[Symbol.hasInstance] () {
return false
}
}
// let f = new Foo()
let fs = new FoocSun()
// console.log(Symbol.hasInstance(f))
console.log(fs)
console.log(Fooc[Symbol.hasInstance](fs))
}
/**
* Symbol.isConcatSpreadable为false或假值或默认值会导致整个对象被追加到数组末尾
* Symbol.isConcatSpreadable为true或真值会导致这个数组元素被打平到数组实例
* 打平:就相当于将数组内部元素提取出来
* Symbol.isConcatSpreadable默认值为undifined,默认值时等同于false
*/
export function symbolIsConcatSpreadable () {
// 数组降维
let a = [1, 2, 3]
let b = [4, [5, 6], 7]
b.forEach((element, index) => {
a = a.concat(b[index])
})
console.log(a)
// IsConcatSpreadable
console.log(b[Symbol.isConcatSpreadable])
console.log(a.concat(b))
b[Symbol.isConcatSpreadable] = false
console.log(a.concat(b))
b[Symbol.isConcatSpreadable] = true
console.log(a.concat(b))
}
/**
* 迭代器,类似于asyncIterator(异步迭代器),
*/
export function symbolIterator () {
class Foo {
constructor (max) {
this.max = max
this.idx = 0
}
* [Symbol.iterator] () {
while (this.idx < this.max) {
yield this.idx++
}
}
}
function acount () {
let f = new Foo(5)
for (const x of f) {
console.log(x)
}
}
acount()
}
/**
* 通过使用参数,改变原有正则匹配字符串
*/
export function symbolMatch () {
console.log('foobar'.match(/ob/))
class FooMatch {
constructor (str) {
this.str = str
}
[Symbol.match] (target) {
return target.includes(this.str)
}
}
console.log('foobar'.match(new FooMatch('ob')))
console.log('bazobar'.match(new FooMatch('ob')))
}
/**
* 重定义替换规则
*/
export function symbolReplace () {
class FooReplace {
constructor (str) {
this.str = str
}
[Symbol.replace] (target, replaceVal) {
console.log(target.split(this.str))
return target.split(this.str).join(replaceVal)
}
}
let fr = new FooReplace('foo')
console.log('barfoobaz'.replace(fr, 'qxx'))
}
/**
* 重定义search规则
*/
export function symbolSearch () {
class FooSearch {
constructor (str) {
this.str = str
}
[Symbol.search] (target) {
return target.indexOf(this.str)
}
}
let fr = new FooSearch('foo')
console.log('barfoobaz'.search(fr))
console.log('foobaz'.search(fr))
}
/**
* 定义:一个函数值,该函数作为创建派生对象的构造函数
* 通过定义静态的获取器(getter),可以覆盖新创建实例的原型定义
*/
export function symbolSpecies () {
class Bar extends Array {}
class Baz extends Array {
static get [Symbol.species] () {
return Array
}
}
let bar = new Bar()
console.log(bar instanceof Array)
console.log(bar instanceof Bar)
bar = bar.concat('bar')
console.log(bar)
console.log(bar instanceof Array)
console.log(bar instanceof Bar)
let baz = new Baz()
console.log(baz instanceof Array)
console.log(baz instanceof Baz)
baz = baz.concat('baz')
console.log(baz)
console.log(baz instanceof Array)
console.log(baz instanceof Baz)
}
/**
* 定义:一个正则表达式方法,该方法在匹配正则表达式的索引位置拆分字符串。由String.prototype.split()方法使用
*/
export function symbolSplit () {
class StringSplit {
constructor (str) {
this.str = str
}
[Symbol.split] (target) {
return target.split(this.str)
}
}
let ss = new StringSplit('abc')
console.log('12abc33'.split(ss))
}
/**
* 定义:一个方法,该方法将对象转换为相应的原始值(基本数据类型值)。由ToPrimitive抽象操作使用
* 函数参数(hint)值仅为number,string,default
*/
export function symbolToPrimitive () {
// 一个没有提供 Symbol.toPrimitive 属性的对象,参与运算时的输出结果
var obj1 = {}
console.log(+obj1) // NaN
console.log(`${obj1}`) // "[object Object]"
console.log(obj1 + '') // "[object Object]"
// 接下面声明一个对象,手动赋予了 Symbol.toPrimitive 属性,再来查看输出结果
var obj2 = {
[Symbol.toPrimitive] (hint) {
console.log('hint=', hint)
if (hint === 'number') {
return 10
}
if (hint === 'string') {
return 'hello'
}
return true
}
}
console.log(Number(obj2)) // 10 -- hint 参数值是 "number"
console.log(`${obj2}`) // "hello" -- hint 参数值是 "string"
console.log(obj2 + 'q') // "true" -- hint 参数值是 "default"
}
/**
* 定义:一个字符串,该字符串用于创建对象的默认字符串描述。由内置方法Object.prototype.toString()使用
*/
export function symbolToStringTag () {
class Bar {
constructor () {
this[Symbol.toStringTag] = 'Bar'
}
}
let bar = new Bar()
console.log(bar.toString())
console.log(bar[Symbol.toStringTag])
}
/**
* 鉴于严格模式下禁止使用with,因此不推荐使用该内置符号。不做深入研究
* 定义:一个对象,该对象所有的以及继承的属性,都会从关联对象的with环境绑定中排除
*/
export function symbolUnsopables () {
'use script'
let o = { foo: 'bar' }
// with(o){
// console.log(foo)
// }
o[Symbol.unscopables] = {
foo: true
}
// with(o){
// console.log(foo)
// }
}