一、WeakMap与WeakSet(了解)
(1)WeakMap/WeakSet与map/set区别
-
和map/set基本完全一致,可以理解成阉割版的map/set,为什么是阉割?看一下其原型:
-
weakMap原型
WeakMap {} [[Entries]] No properties [[Prototype]]: WeakMap constructor: ƒ WeakMap() delete: ƒ delete() get: ƒ () has: ƒ has() set: ƒ () Symbol(Symbol.toStringTag): "WeakMap" [[Prototype]]: Object
-
weakSet原型
WeakSet {} [[Entries]] No properties [[Prototype]]: WeakSet add: ƒ add() constructor: ƒ WeakSet() delete: ƒ delete() has: ƒ has() Symbol(Symbol.toStringTag): "WeakSet" [[Prototype]]: Object
发现map/set上的遍历方法全都没有了,所以说是阉割版
-
-
存储的成员只能是对象
let ws = new WeakSet(); ws.add(1); // 报错 ws.add({'t':1}); // WeakSet {{t:1}} let wm = new WeakMap(); wm.set('t',1); // 报错 wm.set({'t':1},1); // WeakMap {{…} => 1}
-
回收机制不一样,它们属于弱引用,JS垃圾回收不会考虑它们的引用
不能遍历,是因为成员都是弱引用,随时可能消失,遍历不能保证成员的存在,可能刚刚遍历结束,成员就取不到了。
二、proxy与reflect
(1)proxy
代理,即对操作符进行拦截处理
let star = {
name :'li**',
age:'25',
phone:'star 128888888888'
}
let agent = new Proxy(star,{
// 拦截读取操作
get:function(target,key){
if(key === 'phone'){
return 'agent: 1281234567'
}
if(key === 'price'){
return 12000
}
return target[key]
},
// 拦截赋值操作
set:function(target,key,value){
if(value < 10000){
throw new Error('价格太低')
}else{
target[key] = value;
return true; //象征性操作,说明赋值成功
}
},
// 拦截 in 操作符
has:function(target,key){
console.log('请联系agent')
if(key === 'customPrice'){
return target[key]
}else{
return false;
}
},
// 拦截 delete 操作
deleteProperty: function(target, key){
if (key.indexof('_') === 0){
delete target [key];
return false;
}
},
// 拦截 getOwnPropertyNames、getOwnPropertySymbols、keys 操作
ownKeys: function(target) {
console.log(1);
console.log(target);
return []; // 不返回数组会报错
},
// ... 还可以拦截其它,Reflect上有的方法都可在这里配置
})
console.log(agent.phone)//agent: 1281234567
console.log(agent.price)//12000
console.log(agent.name)//li**
console.log(agent.age)//25
agent.customPrice = 1500000; //1500000
console.log(agent.customPrice); //1500000
console.log('customPrice' in agent); //请联系agent false
//has是没有办法拦截for in的
for(let key in agent) {
console.log(agent[key]);
}
console.log(delete agent.name); //false 拦截了删除
console.log(Object.getOwnPropertyNames(agent));
//1 {name: 'li**', age: '25', phone: 'star 128888888888'} []
其他代理操作:
get(target, propKey, receiver)
:拦截对象属性的读取,比如 proxy.foo 和 proxy[‘foo’]set(target.propKey, value, receiver)
:拦截对象属性的设置,比如 proxy.foo=v 或 proxy[‘foo’]=v,返回你赋的值has(target, propKey)
:拦截 propKey in proxy的操作,返回一个布尔值deleteProperty(target, propKey)
:delete proxy[propKey]的操作,返回一个布尔值ownKeys(target)
:Object.getOwnPropertyNames(proxy)、Object.getOwnPropertySymbols(proxy)、 Object.keys(proxy),返回一个数组,该方法返回目标对象所有自身的属性的属性名,而Object.keys()的返回结果仅包括目标对象自身的可遍历属性- getOwnPropertyDescriptor(target, propKey):拦截 Object.getOwnPropertyDescriptor(proxy, propKey),返回属性的描述对象。
defineProperty(target, propKey, propDesc)
:拦截Object.defineProperty(proxy, propKey, propDesc)、Object.defineProperties(proxy, propDescs),返回一个布尔值preventExtensions(target)
:拦截 Object.preventExtensions(proxy),返回一个布尔值- getPrototypeOf(target):拦截 Object.getPrototypeOf(proxy),返回一个对象
isExtensible(target)
:拦截 Object.isExtensible(proxy),返回一个布尔值setPrototypeOf(target, proto)
:拦截 Object.setPrototypeOf(proxy, proto),返回一个布尔值,如果目标对象是函数,那么还有两种额外操作可以拦截。apply(target, object, args)
:拦截 Proxy 实例作为函数调用的操作,比如 proxy(…args)、 proxy.call(object,…args)、proxy.apply(…)construct(target, args)
:拦截 Proxy 实例作为构造a数调用的操作,比如 new proxy(…args)
(2)reflect
把一系列的操作符变成了一种函数的行为,和函数调用没什么区别
Reflect {defineProperty: ƒ, deleteProperty: ƒ, apply: ƒ, construct: ƒ, get: ƒ, …}
apply: ƒ apply()
construct: ƒ construct()
defineMetadata: ƒ defineMetadata(metadataKey, metadataValue, target, targetKey)
defineProperty: ƒ defineProperty()
deleteMetadata: ƒ deleteMetadata(metadataKey, target /* , targetKey */)
deleteProperty: ƒ deleteProperty()
enumerate: ƒ enumerate(target)
get: ƒ ()
getMetadata: ƒ getMetadata(metadataKey, target /* , targetKey */)
getMetadataKeys: ƒ getMetadataKeys(target /* , targetKey */)
getOwnMetadata: ƒ getOwnMetadata(metadataKey, target /* , targetKey */)
getOwnMetadataKeys: ƒ getOwnMetadataKeys(target /* , targetKey */)
getOwnPropertyDescriptor: ƒ getOwnPropertyDescriptor()
getPrototypeOf: ƒ getPrototypeOf()
has: ƒ has()
hasMetadata: ƒ hasMetadata(metadataKey, target /* , targetKey */)
hasOwnMetadata: ƒ hasOwnMetadata(metadataKey, target /* , targetKey */)
isExtensible: ƒ isExtensible()
metadata: ƒ metadata(metadataKey, metadataValue)
ownKeys: ƒ ownKeys()
preventExtensions: ƒ preventExtensions()
set: ƒ ()
setPrototypeOf: ƒ setPrototypeOf()
Symbol(Symbol.toStringTag): "Reflect"
[[Prototype]]: Object
var obj = {
a: 1
};
Reflect.get(obj,'a');
Reflect.set(obj,'b',10);
Reflect.has(obj,'a');
Object.defineProperty(target,property,atrributes); //配置错误会报错
Reflect.defineProperty(target,property,atrributes); //配置错误返回false