ECMAScript6(12):Proxy 和 Reflect

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前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
减轻大家的负担。**

[外链图片转存中…(img-quCSR5xR-1714851675182)]

[外链图片转存中…(img-WLwfvmdc-1714851675183)]

[外链图片转存中…(img-HHzreDq2-1714851675183)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点!不论你是刚入门Android开发的新手,还是希望在技术上不断提升的资深开发者,这些资料都将为你打开新的学习之门!

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值