携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第18天,点击查看活动详情 >>
handler.isExtensible()
在判断代理对象是否可扩展时,将会触发该操作。触发的方式包括有使用Object.isExtensible()以及Reflect.isExtensible()
const monster1 = {
canEvolve: true
};
const handler1 = {
isExtensible(target) {
return Reflect.isExtensible(target);
},
preventExtensions(target) {
target.canEvolve = false;
return Reflect.preventExtensions(target);
}
};
const proxy1 = new Proxy(monster1, handler1);
console.log(Object.isExtensible(proxy1));
// expected output: true
console.log(monster1.canEvolve);
// expected output: true
Object.preventExtensions(proxy1);
console.log(Object.isExtensible(proxy1));
// expected output: false
console.log(monster1.canEvolve);
// expected output: false
解释一下上面的代码里关键的部分,首先,preventExtensions是将对象作为参数,把对象设置为不可添加新的属性,他可以删除现有属性,也可以修改现有属性,返回值是原来的对象, 对代理对象的修改会映射在原对象上,代理对象的isExtensible是false,代理对象是不能添加属性的,针对代理对象的修改会同步至原对象
handler.preventExtensions()
在演示是否支持扩展的时候已经涉及了,不再赘述
handler.getOwnPropertyDescriptor()
在获取代理对象的属性描述时,将会触发该操作。触发的方式包括有使用Object.getOwnPropertyDescriptor()以及Reflect.getOwnPropertyDescriptor()
var p = new Proxy({ a: 20}, {
getOwnPropertyDescriptor: function(target, prop) {
console.log('called: ' + prop);
return { configurable: true, enumerable: true, value: target[prop] };
}
});
console.log(Object.getOwnPropertyDescriptor(p, 'a').value);
getOwnPropertyDescriptor接受两个参数,target和property,而且,返回的对象必须符合声明对象的对象属性描述符,随意添加的属性是不被解析的,如下图所示
对象属性描述符
对象属性描述符是由下面的一个或几个组成的,自定义的属性描述符无效
-
value -
该属性的值 (仅针对数据属性描述符有效)
-
writable -
当且仅当属性的值可以被改变时为 true。(仅针对数据属性描述有效) -
get -
获取该属性的访问器函数(getter)。如果没有访问器,该值为 undefined。(仅针对包含访问器或设置器的属性描述有效)
-
set -
获取该属性的设置器函数(setter)。如果没有设置器,该值为 undefined。(仅针对包含访问器或设置器的属性描述有效)
-
configurable -
当且仅当指定对象的属性描述可以被改变或者属性可被删除时,为 true。 -
enumerable -
当且仅当指定对象的属性可以被枚举出时,为
true。
handler.defineProperty()
在定义代理对象的某个属性时,将会触发该操作。触发的方式包括有使用Object.defineProperty()以及Reflect.defineProperty()还有就是直接定义属性名和属性值例如proxy.aa = 5
var p = new Proxy({}, {
defineProperty: function(target, prop, descriptor) {
console.log('called: ' + prop);
return true;
}
});
var desc = { configurable: true, enumerable: true, value: 10 };
Object.defineProperty(p, 'a', desc); // "called: a"
同样的,defineProperty也只能定义标准的属性描述符,非标准的属性描述符会被忽略,也就是说,我们只能使用上面列出的对象属性描述符来对属性进行定义