var proxy = new Proxy({},{
get: function(target, key){
return 35;
}
});
var obj = Object.create(proxy);
obj.time = 20;
console.log(obj.time); //20
console.log(obj.name); //35
感受一下它的威力:
var obj = new Proxy({}, {
get: function(target, key, receiver){
console.log(getting ${key} ...
);
return Reflect.get(target, key, receiver);
},
set: function(target, key, value, receiver){
console.log(setting ${key} ...
);
return Reflect.set(target, key, value, receiver);
}
});
obj.count = 1; //setting count …
++obj.count; //getting count …
//setting count …
console.log(obj.count); //getting count …
//2
可以看出来,handler对象中 get 方法表示属性的访问请求,set 方法表示属性的写入请求。
当然不仅仅 get 和 set, 我们可以定义以下拦截函数:
- get(target, propKey, receiver = target)
拦截对象的读取属性。当 target 对象设置了 propKey 属性的 get 函数时,receiver 绑定 get 函数的 this。返回值任意
- set(target, propKey, value, receiver = target)
拦截对象的写入属性。返回一个布尔值
- has(target, propKey)
拦截 propKey in proxy 操作符,返回一个布尔值
- deleteProperty(target, propKey)
拦截 delete proxy[propKey] 操作符,返回一个布尔值
- enumerate(target)
拦截 for(let i in proxy) 遍历器,返回一个遍历器
- hasOwn(target, propKey)
拦截 proxy.hasOwnProperty(‘foo’),返回一个布尔值
- ownKeys(target)
拦截 Object.getOwnPropertyNames(proxy), Object.getOwnPropertySymbols(proxy), Object.keys(proxy),返回一个数组。该方法返回对象所有自身属性,包括不可遍历属性,不包括 Symble属性,但是Object.keys(proxy)
不应该包括不可遍历属性
- getOwnPropertyDescriptor(target, propKey)
拦截 Object.getOwnPropertyDescriptor(proxy, propKey),返回其属性描述符
- defineProperty(target, propKey, propDesc)
拦截 Object.defineProperty(proxy, propKey, propDesc), Object.defineProperties(proxy, propDesc),返回一个布尔值
- 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(object, args)
- construct(target, args, proxy)
拦截用 new 调用 proxy 函数的操作,construct()返回的不是对象会报错
以下列举一些 Proxy 的实例
访问对象不存在的属性报错
var obj = new Proxy({}, {
get: function(target, key){
if(key in target){
return Reflect.get(target, key);
} else {
throw new ReferenceError("${key}" is not in object
);
}
}
});
obj.look = “picture”;
console.log(obj.look); //“picture”
console.log(obj.sleep); //ReferenceError: “sleep” is not in object
数组索引为负时返回倒数位置的值
var origin = [10,20];
var arr = new Proxy(origin, {
get(target, key){
let index = parseInt(key);
if(index < 0){
index = target.length + index;
if(index < 0) return undefined;
}
return Reflect.get(target, index);
}
});
console.log(arr[0]); //10
console.log(arr[1]); //20
console.log(arr[2]); //undefined
console.log(arr[-1]); //20
console.log(arr[-4]); //undefined
保护对象内以 “_” 开头的属性为私有属性:
var o = {
“_name”: “Bob”,
“age”: 13,
“_fun”: function(){
console.log(“_fun is called”);
}
};
var obj = new Proxy(o, {
get(target, key){
if(key.charAt(0) === ‘_’){
return undefined;
}
return Reflect.get(target, key);
},
set(target, key, value){
if(key.charAt(0) === ‘_’){
throw new Error(‘Cannot define a property begin with “_”’);
}
return Reflect.set(target, key, value);
},
has(target,key){
if(key.charAt(0) === ‘_’){
return false;
}
return Reflect.has(target, key);
},
deleteProperty(target,key){
if(key.charAt(0) === ‘_’){
return false;
} else {
Reflect.deleteProperty(…arguments);
}
},
apply(target,ctx,args){
if(target.name.charAt(0) === ‘_’){
throw new TypeError(${target.name} is not defined
);
} else {
Reflect apply(…arguments);
}
},
defineProperty(target,key,desc){
if(key.charAt(0) === ‘_’){
return new Error(cannot define property begin with "_"
);
} else {
Reflect.defineProperty(…arguments);
}
},
setPrototypeOf(target,proto){
throw new TypeError(Cannot change the proto of ${target}
);
},
construct(target,ctx,args){
if(target.name.charAt(0) === ‘_’){
throw new TypeError(${target.name} is not defined
);
} else {
Reflect construct(…arguments);
}
}
});
console.log(obj.age); //13
obj.age = 20;
console.log(obj.age); //20
console.log(obj._name); //undefined
obj.hobby = “Coding”; //Error: Cannot define a property begin with ""
_name in key //false
delete obj._name;
Object.defineProperty(obj,“_hobby”,{
value: “Coding”
});
Object.defineProperties(obj,{
‘_hobby’: {
value: “Coding”
}
});
obj._fun();
var a = new obj._fun();
obj.proto = {}; //Cannot define a property begin with “_”
Object.setPrototypeOf(obj,{}) //Cannot change the proto of obj
当然不是所有 proxy 代理都不可取消,下面方法设置的代理是可以通过定义代理时返回的revoke函数取消:
var a = {
name:“Bob”
};
var {proxy, revoke} = Proxy.revocable(a, {
get(target,key){
return undefined;
}
});
proxy.name; //undefined;
revoke();
proxy.name; //TypeError: Cannot perform ‘get’ on a proxy that has been revoked
最后
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。
因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!
如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
减轻大家的负担。**
[外链图片转存中…(img-quCSR5xR-1714851675182)]
[外链图片转存中…(img-WLwfvmdc-1714851675183)]
[外链图片转存中…(img-HHzreDq2-1714851675183)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!
如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!