# Symbol 类型

WARNING

  • 基础
  • 作为属性名
  • 属性名的遍历
  • Symbol.for 和 Symbol.keyFor
  • 11个内置 Symbol 值

可以用来表示独一无二的值

let s1 = Symbol('xiao')
let s2 = Symbol('xiao')
console.log(s1 === s2) // false
1
2
3

不可以和其他类型的值做运算

let s2 = Symbol('xiao')
2 + s2
1
2

静态图片

可以转换成字符串类型和布尔类型

let s2 = Symbol('xiao')
console.log(s2.toString()) // Symbol(xiao)
console.log(Boolean(s2)) // true
1
2
3

可以用作属性名,使用 symbol 作为属性名的好处就是独一无二不会被覆盖。

// 对象属性名
let prop = 'name'
let objSymbol = {
	name: '小鱼',
	[`my${prop}`]: '小铜钱'
}


let s3 = Symbol('name')
let objSymbol2 = {
	[s3]: '你好'
}

// 修改值
objSymbol2[s3] = '修改了'

// objSymbol2.s3 不能这么修改

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

属性名的遍历

let objSymbol2 = {
	[s3]: '你好',
	age: 19
}

for (let key in objSymbol2) {
	console.log(key, 'key--') // 只有 age
}

console.log(Object.keys(objSymbol2), '属性名') // ['age'] 只有 age

console.log(Object.getOwnPropertyNames(objSymbol2)) // ['age'] 只有 age

console.log(JSON.stringify(objSymbol2)) // {"age":19}

// 获取symbol属性
console.log(Object.getOwnPropertySymbols(objSymbol2))


// 获取所有属性名
console.log(Reflect.ownKeys(objSymbol2)) // ['age', Symbol(name)]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

Symbol.for 方法

使用 Symbol.for() 创建的时候,会先查找是否已经创建过了,如果是则返回


let s4 = Symbol.for('xiao')
let s5 = Symbol.for('xiao')
console.log(s4 === s5) // true

1
2
3
4
5

Symbol.keyFor() 返回一个标识

let s4 = Symbol.for('xiao')
console.log(Symbol.keyFor(s4)) // xiao
1
2

# 11 个内置的 Symbol 值

Symbol.hasInstance

let obj2 = {
	[Symbol.hasInstance](otherObj: any) {
		console.log(otherObj, '实例') // { a: '1' }
	}
}

console.log({ a: '1' } instanceof <any>obj2, '测试-a') // false

1
2
3
4
5
6
7
8

Symbol.isConcatSpreadable 可读写的布尔值,默认是 undefined, 是否可扁平化

let arr = [1, 2]
console.log([].concat(arr, [3, 4])) // [1, 2, 3, 4]
arr[Symbol.isConcatSpreadable] = false
console.log([].concat(arr, [3, 4])) // 此时不会被扁平化了
1
2
3
4

Symbol.species 可以指定衍生对象的构造函数

class C extends Array {
	getName () {
		return 'xiao'
	}
}
const c = new C(1, 2, 3)
const a = c.map(item => {
	return item + 1
})

c instanceof C // true
c instanceof Array // true
a instanceof C // true
a instanceof Array // true
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class C extends Array {
	constructor(...args) {
		super(...args);
	}
	static get[Symbol.species]() {
		return Array
	}
	getName () {
		return 'xiao'
	}
}
const c = new C(1, 2, 3)
const a = c.map(item => {
	return item + 1
})

c instanceof C // true
c instanceof Array // true
a instanceof C // false  这里是有区别的
a instanceof Array // true
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

Symbol.match


let obj3 = {
	[Symbol.match](str: string) {
		console.log(str.length)
	}
}

'abc2'.match(<RegExp>obj3) // 4

1
2
3
4
5
6
7
8
9

Symbol.replaceSymbol.searchSymbol.split 和上面的 match 都是使用在字符串上的方法

Symbol.iterator 数组是否可迭代


let arrD = [1, 2, 3]
let iterator = arrD[Symbol.iterator]()
iterator.next() // { value: 1, done: false }
iterator.next() // { value: 2, done: false }
iterator.next() // { value: 3, done: false }
iterator.next() // { value: undefined, done: true }

1
2
3
4
5
6
7
8

Symbol.toPrimitive 对象被转成原始类型值的时候,会调用这个方法。(隐式类型转换)

let objStr = {
	[Symbol.toPrimitive](type) {
		console.log(type, '类型') // number
	}
}

let res = objStr++
1
2
3
4
5
6
7
let objStr = {
	[Symbol.toPrimitive](type) {
		console.log(type, '类型') // string
	}
}
let resStr = `abc${objStr}`
1
2
3
4
5
6

Symbol.toStringTag 可以指定属性值, 对象调用 toString 的时候,会调用 toStringTag

let objStr = {
	[Symbol.toStringTag]: 'xiao'
}
console.log(objStr.toString()) // [object xiao] 
1
2
3
4
let objStr = {
	get [Symbol.toStringTag]() {
		return 'xiao'
    }
}
console.log(objStr.toString()) // [object xiao] 
1
2
3
4
5
6

Symbol.unscopables 和 with 有关

let objData = {
	a: 'a-1',
	b: 'b-1'
}
with (objData) {
	console.log(a) // a-1
	console.log(b) // b-1
}

console.log(Array.prototype[Symbol.unscopables]) 
// 数组被过滤的掉的方法
at: true
copyWithin: true
entries: true
fill: true
find: true
findIndex: true
findLast: true
findLastIndex: true
flat: true
flatMap: true
includes: true
keys: true
values: true
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24