ES5:Object.defineProperty()的作用就是直接在一个对象上定义一个新属性,或者修改一个已经存在的属性。
详细讲解
基本用法:
Object.defineProperty(obj, prop, desc)
参数说明:
- obj 需要定义属性的当前对象
- prop 当前需要定义的属性名
- desc 属性描述符
通过Object.defineProperty()为对象定义属性,有两种形式,且不能混合使用,分别为数据描述符,存取描述符。
数据描述符:
writeable:是否可以修改
let person = {}
Object.defineProperty(person,'name',{
value:'张三',
writeable:false//默认为false,默认可省略
})
person.name = '李四'
console.log(person.name);//张三
let person = {}
Object.defineProperty(person,'name',{
value:'张三',
writeable:true//默认为false,默认可省略
})
person.name = '李四'
console.log(person.name);//李四
存取描述符:
get:一个给属性提供getter的方法,如果没有getter则为undefined。该方法返回值被用作属性值。默认为undefined。
set:一个给属性提供setter的方法,如果没有setter则为undefined。该方法将接受唯一参数,并将该参数的新值分配给该属性。默认值为undefined。
let person = {}
let temp = null;//给他赋值,防止set方法陷入死循环
Object.defineProperty(person,name,{
get: function() {
return temp;
},
set: function(val) {
temp = val;
}
})
person.name = '张三';
console.log(person.name);
注意
数据描述符和存取描述均具有以下描述符
configrable 能否使用delete、能否需改属性特性、或能否修改访问器属性
enumerable 描述属性是否会出现在for in 或者 Object.keys()的遍历中
let person = {};
Object.defineProperty(person, 'name', {
value: '张三',
writable: true,
configurable: false
})
//person.name = '李四';
Object.defineProperty(person, 'name', {
value: '李四',
})
console.log(person.name); //Cannot redefine property: name
let person = {
name: "张三",
};
Object.defineProperty(person, "name", {
configurable: false,
enumerable: true,
writable: false,
});
delete p.name;//"TypeError: Cannot delete property 'name' of #<Object>"
configrable:true 通过属性定义的方式可以被修改
let person = {};
Object.defineProperty(person, 'name', {
value: '张三',
configrable: true,
writable: true,
enumerable: true
})
Object.defineProperty(person, 'name', {
value: 'lisi',
})
console.log(person);//lisi
delete person.name
console.log(person);//undefine
<meta charset="utf-8">
enumerable:
enumerable.png 默认属性值.png
对象常量
结合writable: false 和 configurable: false 就可以创建一个真正的常量属性(不可修改,不可重新定义或者删除)
对象常量.png
禁止扩展:
let person = {
name: "张三",
};
Object.preventExtensions(person)
person.gender = '女';//"TypeError: Cannot add property gender, object is not extensible"
console.log(person);
密封
Object.seal()会创建一个密封的对象,这个方法实际上会在一个现有对象上调用object.preventExtensions(...)并把所有现有属性标记为configurable:false。
所以, 密封之后不仅不能添加新属性,也不能重新配置或者删除任何现有属性(虽然可以改属性的值)
冻结: vue中纯数据的展示,可以冻结对象,取消绑定,提升性能
Object.freeze()会创建一个冻结对象,这个方法实际上会在一个现有对象上调用Object.seal(),并把所有现有属性标记为writable: false,这样就无法修改它们的值。
冻结.png
ES6:Proxy 可以理解成,在目标对象之前架设一层“拦截”,外界对该对象的访问,都必须先通过这层拦截,因此提供了一种机制,可以对外界的访问进行过滤和改写
基本用法:
let p = new Proxy(target, handler);
参数说明:
1.target :需要使用Proxy包装的目标对象(可以是任何类型的对象,包括原生数组,函数,甚至另一个代理)。
2.handler: 一个对象,其属性是当执行一个操作时定义代理的行为的函数(可以理解为某种触发器)。具体的handler相关函数请查阅官网
①get:属性读取操作的捕捉器
let person = {
name:'张三',
age:18
}
person = new Proxy(person,{
get(target,key) {
console.log('获取属性');
if (key === 'age') {
return target[key] +'岁'
}
return target[key];
}
})
console.log(person.age);//18岁
②set:属性设置操作的捕捉器。
let person = {
name:'张三',
age:18
}
person = new Proxy(person,{
set(target,key,val) {
console.log('设置属性');
if(typeof target[key] === 'number'){
target[key] = val + '岁';
}else{
target[key] = val;
}
}
})
person.age = 19;
console.log(person.age);
③has:操作符的捕捉器。检查是否存在属性。
//has
let range= {
start:1,
end:5
}
range = new Proxy(range,{
has:function(target,key){
return key >= target.start && key <= target.end;
}
})
console.log(2 in range);//true
console.log(9 in range);//false
④ownkeys:对对象的循环遍历进行拦截
//保护_password不可被遍历
let person = {
name: '张三',
age: 18,
_password: '****'
}
person = new Proxy(person, {
ownKeys(target) {
return Object.keys(target).filter(item =>
!item.startsWith('_')
)
}
});
console.log(Object.keys(person));//['name', 'age']
⑤deleteProperty:删除拦截器
let person2 = {
name: '李四',
age: 19,
_password: '****'
}
person2 = new Proxy(person2, {
deleteProperty(target, prop) {
if (prop.startsWith('_')) {
throw new Error('不可删除')
} else {
delete target[prop];
return true;
}
}
})
try {
delete person2._password
} catch (e) {
console.log(e.message);//不可删除
}
⑥apply拦截函数操作
let sum = function (...args) {
let sum = 0;
args.forEach(item => {
sum += item;
})
return sum;
}
sum = new Proxy(sum, {
apply(target,context,args) {
return target(...args)*2;
}
})
console.log(sum(1,2,3));//12
console.log(sum.call(null,1,2,3,4));//20
console.log(sum.apply(null,[1,2,3,4]));//20
⑦construct 拦截new 命令
function People(name){
this.name = name;
}
console.log(People);
let proxy = new Proxy(People,{
construct:function(target, argumentsList, newTarget) {
console.log('拦截到了');
return new target(...argumentsList);
}
})
console.log(new proxy('张三'));
proxy拦截器总结:
proxy拦截器总结1.png
proxy拦截器总结2.png
Reflect:
reflect详细介绍
网友评论