ES6知识点:Proxy和Reflect详解
Posted 还是不会呀
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ES6知识点:Proxy和Reflect详解相关的知识,希望对你有一定的参考价值。
ES6知识点:Proxy和Reflect
ES6新增一个代理类:
Proxy
。监听一个对象的相关操作,可以创建一个对应的代理对象,对原对象的操作通过代理对象来完成。ES6新增一个对象:
Reflect
(反射),用来替换Object内的一些方法。
Proxy的基本使用
修改代理对象,原对象会发生对应改变
const info = { name: "fzb", age: 21 };
const proxy = new Proxy(info, {});
proxy.name = "zkl";
proxy.age = 22;
// 修改代理对象,原对象也会发生对应改变
console.log(info); // { name: 'zkl', age: 22 }
Proxy的十三种捕获器
最常用
的是前面四种
捕获器
set和get捕获器
对对象的取值和设置进行拦截
const info = { name: "fzb", age: 21 };
//为info对象创建
const proxy = new Proxy(info, {
// target:原对象, key:操作的key, receiver: 创建的代理对象
get: function (target, key, receiver) {
console.log(`拦截到正在获取${key}`, target);
return target[key];
},
// newValue: 设置值的新值
set: function (target, key, newValue, receiver) {
console.log(`拦截到正在设值的${key}`, target);
target[key] = newValue;
},
});
console.log(proxy.name);
proxy.age = 22;
// 控制台打印:
// 拦截到正在获取name { name: 'fzb', age: 21 }
// fzb
// 拦截到正在设值的age { name: 'fzb', age: 21 }
has捕获器
对in
操作进行拦截
const info = { name: "fzb" };
const proxy = new Proxy(info, {
has: function (target, key) {
console.log(`拦截到in操作符,属性是:${key}`);
return key in target;
},
});
console.log("name" in proxy); // true
// 控制台打印:
// 拦截到in操作符,属性是:name
// true
deleteProperty捕获器
对属性的删除(delete
关键字)进行拦截
const info = { name: "fzb" };
const proxy = new Proxy(info, {
deleteProperty: function (target, key) {
console.log(`拦截到key值为${key}的删除操作`);
delete target[key];
},
});
delete proxy.name; // 拦截到key值为name的删除操作
console.log(proxy); // {}
getPrototypeOf捕获器
对获取对象的原型(Object.getPrototypeOf
)时进行拦截
const info = {};
const proxy = new Proxy(info, {
getPrototypeOf: function (target) {
console.log(`拦截到了获取原型的过程`);
return Object.getPrototypeOf(target);
},
});
console.log(Object.getPrototypeOf(proxy));
// 浏览器打印:
// 拦截到了设置原型的过程
// [Object: null prototype] {}
setPrototypeOf捕获器
在设置对象原型(Object.setPrototypeOf
)时进行拦截
const info = {};
const proxy = new Proxy(info, {
setPrototypeOf: function (target, object) {
console.log(`拦截到了设置原型的过程`);
return Object.setPrototypeOf(target, object);
},
});
Object.setPrototypeOf(proxy, {}); // 拦截到了设置原型的过程
console.log(proxy.__proto__); // {}
isExtensible捕获器
在对象进行扩展属性(Object.isExtensible
)时进行拦截
const info = {};
const proxy = new Proxy(info, {
isExtensible: function (target) {
console.log(`拦截到了对象允许进行扩展新的属性`);
return Object.isExtensible(target);
},
});
console.log(Object.isExtensible(proxy));
// 浏览器打印:
// 拦截到了对象允许进行扩展新的属性
// true
preventExtensions捕获器
在对象不准进行扩展属性(Object. preventExtensions
)时进行拦截
const info = {};
const proxy = new Proxy(info, {
preventExtensions: function (target) {
console.log(`拦截到了对象不允许进行扩展新的属性`);
return Object.preventExtensions(target);
},
});
console.log(Object.preventExtensions(proxy));
// 浏览器打印:
// 拦截到了对象不允许进行扩展新的属性
// {}
getOwnPropertyDescriptor捕获器
在获取对象的某个key值得属性描述符(Object.getOwnPropertyDescriptor
)时进行拦截
const info = { name: "fzb" };
const proxy = new Proxy(info, {
getOwnPropertyDescriptor: function (target, key) {
console.log(`拦截到获取key值为${key}的描述器的过程`);
return Object.getOwnPropertyDescriptor(target, key);
},
});
console.log(Object.getOwnPropertyDescriptor(proxy, "name"));
// 浏览器打印:
// 拦截到获取key值为name的描述器的过程
// { value: 'fzb', writable: true, enumerable: true, configurable: true }
defineProperty捕获器
在设置对象得属性描述符(Object.defineProperty
)时进行拦截
const info = { name: "fzb" };
const proxy = new Proxy(info, {
defineProperty: function (target, key, attributes) {
console.log(`拦截到为key值为${key}的设置描述器的过程`);
return Object.defineProperty(target, key, attributes);
},
});
console.log( Object.defineProperty(proxy, "age", {
configurable: true,
writable: true,
enumerable: true,
value: 21,
})
);
// 浏览器打印:
// 拦截到为key值为age的设置描述器的过程
// { name: 'fzb', age: 21 }
apply捕获器
函数在进行apply
调用时进行拦截
function foo(...args) {
console.log(this, args);
}
const proxy = new Proxy(foo, {
apply: function (target, thisArg, argArray) {
console.log(`拦截到函数apply执行方式的过程`);
return target.apply(thisArg, argArray);
},
});
proxy.apply("fzb", [1, 2, 3, 4]);
// 浏览器打印:
// 拦截到函数apply执行方式的过程
// [String: 'fzb'] [ 1, 2, 3, 4 ]
construct捕获器
函数通过new
关键字调用时拦截
function Person() {}
const proxy = new Proxy(Person, {
// newTarget在Reflect时的用法
construct: function (target, argArray, newTarget) {
console.log(`函数进行了new调用`);
return new target(...argArray);
},
});
new proxy(); // 函数进行了new调用
ownKeys捕获器
在获取对象的key(Object.getOwnPropertyNames
和Object.getOwnPropertySymbols
)值时进行拦截
Reflect的基本使用
Reflect
的常用方法
包含了类似in
和delete
操作符的一些方法
Reflect和Proxy一起使用
在上方Proxy
的十三种捕获器内的操作,其实还是直接在原对象上操作
const info = {};
const proxy = new Proxy(info, {
set(target, kry, newValue, receiver) {
return Reflect.set(target, kry, newValue, receiver);
},
get(target, key, receiver) {
return Reflect.get(target, key, receiver);
},
has(target, key) {
return Reflect.has(target, key);
},
deleteProperty(target, key) {
return Reflect.deleteProperty(target, key);
},
setPrototypeOf(target, object) {
return Reflect.setPrototypeOf(target, object);
},
getPrototypeOf(target) {
return Reflect.getPrototypeOf(target);
},
getOwnPropertyDescriptor(target, key) {
return Reflect.getOwnPropertyDescriptor(target, key);
},
isExtensible(target) {
return Reflect.isExtensible(target);
},
preventExtensions(target) {
return Reflect.preventExtensions(target);
},
ownKeys(target) {
return Reflect.ownKeys(target);
},
apply(target, thisArg, argArray) {
return Reflect.apply(target, thisArg, argArray);
},
construct(target, argArray, newTarget) {
return Reflect.construct(target, argArray, newTarget);
},
});
对于Reflect.ownKeys
还是只能得到key不为Symbol
的
Reflect.receiver的作用
只有set
和get
存在receiver
const info = {
_name: "fzb",
set name(newValue) {
this._name = newValue;
},
get name() {
return this._name;
},
};
const proxy = new Proxy(info, {
// get: function (target, key, receiver) {
// console.log("-------");
// return Reflect.get(target, key);
// },
// set: function (target, key, newValue, receiver) {
// return Reflect.set(target, key, newValue);
// },
get: function (target, key, receiver) {
console.log("-------");
return Reflect.get(target, key, receiver);
},
set: function (target, key, newValue, receiver) {
return Reflect.set(target, key, newValue, receiver);
},
});
console.log(proxy.name);
// "-------" /n "fzb"
// 解析: 取到的值是正确的,获取name时确实是通过proxy,但是分割线只打印了一次
// 在name访问器获取或设置_name的时候,这时的this已经是info
// receiver就是创建的代理对象,Reflect传入receiver会将内部的this改为代理对象
// proxy内代码注释,并且传入receiver后打印:
// -------
// -------
// fzb
Reflect.construct的使用
function Person() {}
function Student() {}
const stu1 = new Student();
console.log(stu1.__proto__ === Student.prototype); // true
const stu2 = Reflect.construct(Person, [], Student);
// 通过Person创建出来的对象,但是类型却是:Student类型
console.log(stu2.__proto__ === Student.prototype); // true
以上是关于ES6知识点:Proxy和Reflect详解的主要内容,如果未能解决你的问题,请参考以下文章