Proxy
优势
1.监视数据的读写
const person = {
name: 'zce',
age: 20
}
const personProxy = new Proxy(person, {
deleteProperty (target, property) {
console.log('delete', property)
delete target[property]
}
// 监视属性读取
get (target, property) {
return property in target ? target[property] : 'default'
},
// 监视属性设置
set (target, property, value) {
if (property === 'age') {
if (!Number.isInteger(value)) {
throw new TypeError(`${value} is not an int`)
}
}
target[property] = value
}
console.log(personProxy.name) // zce
console.log(personProxy.xxx) //default
delete personProxy.age // delete age
2.监视数组操作
const list = []
const listProxy = new Proxy(list, {
set (target, property, value) {
console.log('set', property, value)
target[property] = value
return true // 表示设置成功
}
})
listProxy.push(100)
输出:
set 0 100
set length 1
3.非侵入的方式监管了对象的读写
// Object.defineProperty监听特定属性
const person = {}
Object.defineProperty(person, 'name', {
get () {
console.log('name 被访问')
return person._name
},
set (value) {
console.log('name 被设置')
person._name = value
}
})
Object.defineProperty(person, 'age', {
get () {
console.log('age 被访问')
return person._age
},
set (value) {
console.log('age 被设置')
person._age = value
}
})
person.name = 'jack'
// Proxy可以对整个对象的属性进行监管,不需要指定特定的属性
const personProxy = new Proxy(person, {
get (target, property) {
console.log('get', property)
return target[property]
},
set (target, property, value) {
console.log('set', property, value)
target[property] = value
}
})
personProxy.name = 'jack'
Reflect(统一的对象操作API)
- 是一个静态类
- 统一提供了一套用于操作对象的API(13种)
const obj = {
name: 'zce',
age: 18
}
'name' in obj 等同于 Reflect.has(obj, 'name')
delete obj['age'] 等同于 Reflect.deleteProperty(obj, 'age')
Object.keys(obj) 等同于 Reflect.ownKeys(obj)
// 其他方法继续深究
class类
- 基本用法
class Person {
constructor (name) { // 构造函数
this.name = name
}
say () { // 实例方法,通过实例对象去调用
console.log(this); // Person { name: 'tom' } this指向的某一个实例对象
console.log(`hi, my name is ${this.name}`)
}
static create (name) { // 静态方法(static),通过类型本身去调用,
console.log(this); // [Function: Person] this指向的是当前的类型
return new Person(name)
}
}
const tom = Person.create('tom')
tom.say()
- extends继承
// 继承父类就拥有了父类的所有成员
class Person {
constructor (name) {
this.name = name
}
say () {
console.log(`hi, my name is ${this.name}`)
}
}
class Student extends Person {
constructor (name, number) {
super(name) // 调用父类构造函数
this.number = number
}
hello () {
super.say() // 调用父类成员
console.log(`my school number is ${this.number}`)
}
}
const s = new Student('jack', '100')
s.hello()
输出:
hi, my name is jack
my school number is 100
Set
- 不接受重复的数据,可用于去重
- add方法可进行链式调用
- 遍历采用forEach或者是for...of
- size获取长度
- has判断集合当中是否存在某个特定的值
- delete 删除集合中某个指定的值,删除成功返回true
- clear清除所有值
const s = new Set()
s.add(1).add(2).add(3).add(4).add(2)
console.log(s) // Set { 1, 2, 3, 4 }
s.forEach(i => console.log(i))
for (let i of s) {
console.log(i)
}
console.log(s.size) // 4
console.log(s.has(100)) // false
console.log(s.delete(3)) // true
s.clear()
- 数组去重
const arr = [1, 2, 1, 3, 4, 1]
const result = [...new Set(arr)] // [1,2,3,4]
弱引用版本 WeakSet
差异 :
Set 中会对所使用到的数据产生引用,即便这个数据在外面被消耗,由于Set 引用了这个数据,所以依然不会回收;
而 WeakSet 的特点就是不会产生引用, 一旦数据销毁,就可以被回收,所以不会产生内存泄漏问题。
Map
- 用来映射两个任意类型数据之间的对应关系
- Map的键可以是任意类型的,而对象的键只能是字符串类型
const m = new Map()
const tom = { name: 'tom' }
m.set(tom, 90) // 键为对象
m.has() // 判断某个键是否存在
m.delete() // 删除某个键
m.clear() // 清空
Symbol
- 解决属性名冲突的问题
- 两个 Symbol 永远不会相等
- 使用 Symbol 为对象添加唯一不重复的键
- 模拟实现私有成员
console.log(Symbol() === Symbol()) // false
Symbol('foo') // foo为描述的文本
const obj = {
[Symbol()]: 123 // 计算属性名
}
const name = Symbol()
const person = {
[name]: 'zce', // 私有成员
say () {
console.log(this[name])
}
}
person[Symbol()] // 由于无法创建一样的Symbol值,无法直接访问到 person 中的「私有」成员
person.say()
BigInt类型用于存放更长的数据,总共有8种数据类型
- Symbol.for 相同的字符串返回相同的Symbol值
const s1 = Symbol.for('foo')
const s2 = Symbol.for('foo')
console.log(s1 === s2)
Symbol.for(true) === Symbol.for('true') // true 都会转成字符串
- 内置 Symbol 常量
console.log(Symbol.iterator) // Symbol(Symbol.iterator)
console.log(Symbol.hasInstance) // Symbol(Symbol.hasInstance)
// 自定义toString标签
const obj = {
[Symbol.toStringTag]: 'XObject'
}
console.log(obj.toString()) // [object XObject]
- 通过getOwnPropertySymbols获取对象中Symbol属性
const obj = {
[Symbol()]: 'symbol value',
foo: 'normal value'
}
for (var key in obj) { // 遍历不出来Symbol的属性
console.log(key)
}
console.log(Object.keys(obj)) // 获取不到Symbol属性
console.log(JSON.stringify(obj)) // 获取不到Symbol属性
console.log(Object.getOwnPropertySymbols(obj))