ES6 Proxy实例方法总结
Proxy中方法枚举
handler方法 | 触发方式 |
---|---|
get | 读取某个属性 |
set | 写入某个属性 |
has | in操作符 |
deleteProperty | delete操作符 |
getPrototypeOf | Object.getPrototypeOf() |
setPrototypeOf | Object.setPrototypeOf() |
isExtensible | Object.isExtensible() |
preventExtensions | Object.preventExtensions() |
getOwnPropertyDescriptor | Object.getOwnPropertyDescriptor() |
defineProperty | Object.defineProperty() |
ownKeys | Object.getOwnPropertyNames()、Object.getOwnPropertySymbols() |
apply | 调用一个函数 |
construct | 用new调用一个函数 |
Proxy方法实际应用
get()
get方法用于监听某个属性的读取操作,可以接受三个参数,依次为代理目标对象、读取的属性名称和 Proxy 实例本身(严格地说,是操作行为针对的对象),其中最后一个参数可选。
const person = {
name: 'Lucky',
age: 20,
}
const personProxy = new Proxy(person, {
// 设置接收两个参数:代理目标对象,读取的属性名称
get(target, property) {
if (property in target) {
return target[property]
}
throw new ReferenceError(`Property '${property}' does not exist.`);
},
})
console.log(personProxy.name); // Lucky
console.log(personProxy.add); // 报错 Property 'add' does not exist.
上面代码在get中设置了如果读取目标对象不存在的属性,会抛出一个错误。正常情况下读取对象不存在的属性,只会返回undefined。
set()
set方法用来监听某个属性的赋值操作,可以接受四个参数,依次为代理目标对象、设置的属性名称、设置的属性值和 Proxy 实例本身,其中最后一个参数可选。
const person = {
name: 'Lucky',
age: 20,
}
const personProxy = new Proxy(person, {
// 三个参数:代理目标对象,写入的属性名称, 属性值
set(target, property, value) {
if (property === 'age') {
if (!Number.isInteger(value)) {
throw new TypeError(`'${value}' is not a int`)
}
}
target[property] = value
},
})
personProxy.age = 123
personProxy.age = 'woshiLucky' // 报错 'woshiLucky' is not a int
上面的代码中监听到改变对象属性值的时候对age字段进行了必须是数字的处理,如果更改的值不是数字类型则抛出错误。
has()
has方法用来监听 HasProperty 操作,即判断对象是否具有某个属性时,这个方法会生效。典型的操作就是 in 运算符。
has 方法可以接受两个参数,分别是代理目标对象、需查询的属性名。
const person = {
name: 'Lucky',
age: 20,
}
const personProxy = new Proxy(person, {
// 两个参数:代理目标对象,需要判断是否存在的属性名称
has(target, property) {
// 将返回结果取反
return !(property in target)
},
})
console.log('age' in personProxy); // false
console.log('add' in personProxy); // true
上面的代码中监听到in运算符使用的时候对结果进行了取反的处理,使对象中包含的属性返回false。
deleteProperty()
deleteProperty方法用于监听 delete 操作符,如果这个方法抛出错误或者返回 false,当前属性就无法被 delete 命令删除。
const person = {
name: 'Lucky',
age: 20,
}
const personProxy = new Proxy(person, {
// 两个参数:代理目标对象,属性名称
deleteProperty (target, property) {
// 当属性为age时不做处理
property !== 'age' && delete target[property];
}
})
delete personProxy.age
delete personProxy.name
console.log(person);
上面的代码中监听到 delete 运算符,对age字段不做删除处理。
getPropertyOf()
getPropertyOf方法主要用来监听获取对象原型。主要是监听Object.getPrototypeOf()方法。接收一个参数,代理目标对象。
const person = {
name: 'Lucky',
age: 20,
}
const person1 = {}
const personProxy = new Proxy(person, {
// 参数:当前目标对象
getPrototypeOf(target) {
return person1;
},
})
console.log(Object.getPrototypeOf(personProxy) === person); // false
上面代码中代理的对象是person,在监听到getPrototypeOf方法时返回了person1的对象,所以personProxy不等于person
setPrototypeOf()
setPrototypeOf方法主要用来监听设置对象原型Object.setPrototypeOf()方法。接收两个参数,分别是:需要改变原型的对象、提供原型的对象。
const person = {
name: 'Lucky',
age: 20,
}
const person1 = {}
const personProxy = new Proxy(person, {
// 两个参数:代理目标对象,属性名称
setPrototypeOf(target, proto) {
console.log(target, proto, target === proto);
if (target !== proto) {
return true
}
throw Error('The target object is the same as the current object.')
},
})
Object.setPrototypeOf(personProxy, person1)
Object.setPrototypeOf(personProxy, person) // 报错 The target object is the same..
上面代码重新定义了原型链循环时的报错信息。
isExtensible()
isExtensible方法主要用来监听判断一个对象是否是可扩展的(是否可以在它上面添加新的属性) Object.isExtensible()方法,返回一个布尔值。
const person = {
name: 'Lucky',
age: 20,
}
const personProxy = new Proxy(person, {
// 参数:当前目标对象
isExtensible(target) {
console.log('isIn');
return true;
},
})
Object.isExtensible(personProxy)
// isIn
// true
上面代码中监听到isExtensible的执行打印‘isIn’
preventExtensions()
preventExtensions方法主要用来监听让一个对象变的不可扩展,也就是永远不能再添加新的属性的Object.preventExtensions()方法,该方法必须返回一个布尔值,否则会被自动转为布尔值。
这个方法有一个限制,只有目标对象不可扩展时(即Object.isExtensible(proxy)为false),proxy.preventExtensions 才能返回 true,否则会报错
const person = {
name: 'Lucky',
age: 20,
}
const personProxy = new Proxy(person, {
// 参数:当前目标对象
preventExtensions(target) {
console.log('isIn');
Object.preventExtensions(target);
return true;
},
})
Object.preventExtensions(personProxy)
getOwnPropertyDescriptor()
getOwnPropertyDescriptor方法主要用来监听Object.getOwnPropertyDescriptor()
Object.getOwnPropertyDescriptor()方法返回指定对象上一个自有属性对应的属性描述符。(自有属性指的是直接赋予该对象的属性,不需要从原型链上进行查找的属性)
const person = {
name: 'Lucky',
age: 20,
}
const personProxy = new Proxy(person, {
// 两个参数:代理目标对象,属性名称
getOwnPropertyDescriptor(target, property) {
if (property === 'name') return
return Object.getOwnPropertyDescriptor(target, property);
},
})
console.log(Object.getOwnPropertyDescriptor(personProxy, 'age'));
// { value: 20, writable: true, enumerable: true, configurable: true }
console.log(Object.getOwnPropertyDescriptor(personProxy, 'name'));
//undefined
上面代码中在获取name时处理,返回undefined
defineProperty()
defineProperty方法主要用来监听Object.defineProperty() 方法。
Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象
const person = {
name: 'Lucky',
age: 20,
}
const personProxy = new Proxy(person, {
// 两个参数:代理目标对象,属性名称,要定义或修改的属性描述符(Object)
defineProperty(target, property, valueObj) {
target[property] = valueObj.value;
return true
},
})
personProxy.gender = 'female';
console.log(personProxy); // { name: 'Lucky', age: 20, gender: 'female' }
ownKeys()
ownKeys方法主要用来监听对象自身属性的读取操作
- Object.getOwnPropertyNames()
- Object.getOwnPropertySymbols()
- Object.keys()
- for...in 循环
const person = {
name: 'Lucky',
age: 20,
}
const personProxy = new Proxy(person, {
// 参数:代理目标对象
ownKeys(target) {
return Object.keys(target)
},
})
console.log(Object.keys(personProxy));
apply()
apply方法主要用来监听函数调用call 和 apply 操作。
apply 方法可以接受三个参数,分别是目标对象、目标对象的上下文对象(this)和目标对象的参数数组。
const target = () => 'Target';
const targetProxy = new Proxy(target, {
// 三个参数:目标对象、目标对象的上下文对象(this)和目标对象的参数数组
apply (target, ctx, args) {
return 'apply'
}
})
console.log(targetProxy()); // apply
construct()
construct方法主要用来监听new 命令。
construct 方法可以接受三个参数。分别是目标对象、构造函数的参数对象和创造实例对象时,new 命令作用的构造函数。
class TargetObj {
construct() {
this.a = 'new'
}
}
const targetProxy = new Proxy(TargetObj, {
// 三个参数:目标对象、目标对象的上下文对象(this)和目标对象的参数数组
construct (targets, args) {
console.log(targets, args);
return args
}
})
console.log(new targetProxy(1, 2, 3)); // [1, 2, 3]