菜鸟教程:
https://www.runoob.com/w3cnote/es6-reflect-proxy.html
目录
Proxy是在目标对象之前架设一层“拦截”,外界对该对象的访问,都必须先通过这层拦截,因此提供了一种机制,可以对外界的访问进行过滤和改写。
创建代理
es6中使用代理是通过new一个代理实例对象进行操作:new Proxy(target,handler)
参数说明:
- target:表示所要拦截(代理)的目标对象
- handler:是一个配置对象,对于每一个被代理的操作,需要提供一个对应的处理函数,该函数将拦截对应的操作。
Proxy的拦截操作方法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>proxy</title>
</head>
<body>
<button class="st">修正内容</button>
<button class="gt">获得内容</button>
<span
style="color: rgb(72, 11, 184);"><strong>   obj的属性名:{name、nativeplace、password},password不允许修改</strong></span>
<p></p>
<script>
// 被代理对象
let obj = {
name: '曹操',
nativeplace: '沛国谯郡',
password: '鸡肋'
};
// 代理方法
let bt = document.querySelector('.st');
let pd = document.querySelector('.gt');
var setname = function () {
let setkey = prompt('输入要修改的键');
if (setkey == 'password') {
proxy1.password = setkey;
} else {
let val = obj[setkey];
if (val == undefined) {
alert`输入的键名不存在,请重新输入`;
setname();
} else {
let newvalue = prompt('输入新的键值');
proxy1[setkey] = newvalue;
return;
}
};
};
var getpd = function () {
let getkey = prompt('输入要获取的键');
if (getkey == 'password') {
let pd = prompt('输入我军口令');
if (pd != '鸡肋') {
alert`口令错误,拉出去斩了!!!`;
}
} else {
let val = obj[getkey];
if (val == undefined) {
alert`输入的键名不存在,请重新获取`;
return;
} else {
let hint = `${getkey}的值是:${obj[getkey]}`;
let p = document.querySelector('p');
p.innerHTML = `<span style="color:red;font-size:30px;">${hint}</span>`;
return;
}
}
};
let handler = {
get: function (traget, key) {
getpd();
},
set: function (traget, key, value) {
if (key == 'password') {
alert`你无权修改口令`;
} else {
if (value == traget[key]) {
alert`不能和之前相同,请重新输入`;
setname();
} else if (value == '') {
alert`修改内容不能为空`;
setname();
} else {
console.log(value);
alert`修改成功`;
}
}
}
};
// 创建代理
let proxy1 = new Proxy(obj, handler);
bt.onclick = function () {
setname();
};
pd.onclick = function () {
getpd();
};
</script>
</body>
</html>
get()
get(target, propKey, receiver)
:拦截对象属性的读取。三个参数,依次为目标对象、属性名和 proxy 实例本身(严格地说,是操作行为所针对的对象,也就是所谓的接收器),其中最后一个参数可选。
set()
set(target, Key, value,receiver)
:用来拦截某个属性的赋值操作,对要赋值的数据进行过滤,加工或是权限设置四个参数,依次为 目标对象、 属性名 、属性值 、Proxy 实例本身 其中最后一个参数可选。
注意,严格模式下(’use strict’;),set代理如果没有返回true,就会报错。
apply()
apply(target, object, args):拦截 Proxy 实例作为函数调用的操作
三个参数,分别是 目标对象(目标对象得是函数) 目标对象的上下文对象(this)(需要手动设置的) 目标对象的参数数组。
has()
has(target, propKey):拦截propKey in proxy的操作,返回一个布尔值。 has方法可以接受两个参数,分别是目标对象、需查询的属性名。
has方法用来拦截hasProperty操作,即判断对象是否具有某个属性时,这个方法会生效。典型操作是in运算符( 但对for… in的操作不起作用 )。has方法拦截的是HasProperty操作,而不是HasOwnProperty操作,即has方法不判断一个属性是对象自身的属性,还是继承的属性。
construct()
construct( target,args):用于拦截new命令。construct方法返回的必须是一个对象,否则会报错。两个参数:
target:目标对象
args:构造函数的参数对象
deleteProperty()
deleteProperty(target,key):拦截delete操作,如果这个方法抛出错误或者返回false,当前属性就无法被delete命令删除。
注意,目标对象自身的不可配置(configurable)的属性,不能被deleteProperty方法删除,否则报错。
defineProperty()
defineProperty(target,key,descriptor):拦截了Object.defineProperty操作。
如果目标对象不可扩展(non-extensible),则defineProperty不能增加目标对象上不存在的属性,否则会报错。另外,如果目标对象的某个属性不可写(writable)或不可配置(configurable),则defineProperty方法不得改变这两个设置。
getOwnPropertyDescriptor()
getOwnPropertyDescriptor(target,key):拦截Object.getOwnPropertyDescriptor(),返回一个属性描述对象或者undefined。
getPrototypeOf()
getPrototypeOf(target):用来拦截获取对象原型。包括:
- Object.prototype.__proto__
- Object.prototype.isPrototypeOf()
- Object.getPrototypeOf()
- Reflect.getPrototypeOf()
- instanceof
getPrototypeOf方法的返回值必须是对象或者null,否则报错。另外,如果目标对象不可扩展(non-extensible), getPrototypeOf方法必须返回目标对象的原型对象。
isExtensible()
isExtensible(target):拦截Object.isExtensible操作
该方法只能返回布尔值,否则返回值会被自动转为布尔值。此方法有一个强限制,它的返回值必须与目标对象的isExtensible属性保持一致,否则就会抛出错误。
ownKeys()
ownKeys(target):用来拦截对象自身属性的读取操作。包括:
- Object.getOwnPropertyNames()
- Object.getOwnPropertySymbols()
- Object.keys()
- for…in循环
使用Object.keys方法时,有三类属性会被ownKeys方法自动过滤,不会返回。 目标对象上不存在的属性 属性名为 Symbol 值 不可遍历(enumerable)的属性:目标对象上不存在的属性、属性名为 Symbol 值、不可遍历(enumerable)的属性。
ownKeys方法返回的数组成员,只能是字符串或 Symbol 值(虽说Symbol会被忽略)。如果有其他类型的值,或者返回的根本不是数组,就会报错。
如果目标对象自身包含不可配置的属性,则该属性必须被ownKeys方法返回,否则报错。
如果目标对象是不可扩展的(non-extensible),这时ownKeys方法返回的数组之中,必须包含原对象的所有属性,且不能包含多余的属性,否则报错。
preventExtensions()
preventExtensions(target):拦截Object.preventExtensions()。该方法必须返回一个布尔值,否则会被自动转为布尔值。
这个方法有一个限制,只有目标对象不可扩展时(即Object.isExtensible(proxy)为false),proxy.preventExtensions才能返回true,否则会报错。
setPrototypeOf()
setPrototypeOf(target,proto):用来拦截Object.setPrototypeOf方法。该方法只能返回布尔值,否则会被自动转为布尔值
Proxy.revocable()
Proxy.revocable(traget,handler):返回一个可取消的 Proxy 实例。