[每日一题]面试官问:谈谈你对ES6的proxy的理解?
[每日一题]面试官问:谈谈你对ES6的proxy的理解?
关注「松宝写代码」,精选好文,每日一题
作者:saucxs | songEagle
一、前言
2020.12.23 日刚立的 flag,每日一题,题目类型不限制,可以是:算法题,面试题,阐述题等等。
本文是「每日一题」第 8 题:[每日一题]面试官问:谈谈你对ES6的proxy的理解

往期「每日一题」:
二、什么是Proxy?
Proxy,代理,是ES6新增的功能,可以理解为代理器(即由它代理某些操作)。
Proxy 对象用于定义或修改某些操作的自定义行为,可以在外界对目标对象进行访问前,对外界的访问进行改写。
1、Proxy定义
var proxy = new Proxy(target, handler)
new Proxy()表示生成一个 Proxy 实例
- target:目标对象
- handler:一个对象,其属性是当执行一个操作时定义代理的行为的函数。
注意:要实现拦截操作,必须是对 Proxy 实例进行操作,而不是针对目标对象 target 进行操作。
2、proxy拦截get和set操作
我们先来看一下proxy拦截get和set操作,示例代码如下:
let handler = {
get: function(target, key, receiver) {
console.log(`getter ${key}!`)
return Reflect.get(target, key, receiver)
},
set: function(target, key, value, receiver) {
console.log(`setter ${key}=${value}`)
return Reflect.set(target, key, value, receiver)
}
}
var obj = new Proxy({}, handler)
obj.a = 1 // setter a=1
obj.b = undefined // setter b=undefined
console.log(obj.a, obj.b)
// getter a!
// getter b!
// 1 undefined
console.log('c' in obj, obj.c)
// getter c!
// false undefined
3、proxy覆盖组件的原始行为
我们来看一下,示例代码如下:
let handler = {
get: function(target, key, receiver) {
return 1
},
set: function (target, key, value, receiver) {
console.log(`setting ${key}!`);
return Reflect.set(target, key, value, receiver);
}
}
var obj = new Proxy({}, handler)
obj.a = 5 // setting 5!
console.log(obj.a); // 1
由上面代码看出:Proxy 不仅是拦截了行为,更是用自己定义的行为覆盖了组件的原始行为。
若handler = {},则代表 Proxy 没有做任何拦截,访问 Proxy 实例就相当于访问 target 目标对象。
三、Proxy handle方法
- 1、get(target, key, receiver):拦截 target 属性的读取
- 2、set(target, key, value, receiver):拦截 target 属性的设置
- 3、has(target, key):拦截 key in proxy 的操作,并返回是否存在(boolean值)
- 4、deleteProperty(target, key):拦截 delete proxy[key]的操作,并返回结果(boolean值)
- 5、ownKeys(target):拦截Object.getOwnPropertyName(proxy)、Object.getOwnPropertySymbols(proxy)、Object.keys(proxy)、for ... in循环。并返回目标对象所有自身属性的属性名数组。注意:Object.keys()的返回结果数组中只包含目标对象自身的可遍历属性
- 6、getOwnPropertyDescriptor(target, key):拦截 Object.getOwnPropertyDescriptor(proxy, key),返回属性的描述对象
- 7、defineProperty(target, key, desc):拦截Object.defineProperty(proxy, key, desc)、Object.defineProperties(proxy, descs),返回一个 boolean 值
- 8、preventExtensions(target):拦截Object.preventExtensions(proxy),返回一个 boolean 值
- 9、getPrototypeOf(target):拦截Object.getPrototypeOf(proxy),返回一个对象
- 10、isExtensible(target):拦截Object.isExtensible(proxy),返回一个 boolean 值
- 11、setPrototypeOf(target, key):拦截Object.setPrototypeOf(proxy, key),返回一个 boolean 值。如果目标对象是函数,则还有两种额外操作可以被拦截
- 12、apply(target, object, args):拦截 Proxy 实例作为函数调用的操作,比如proxy(...args)、proxy.call(object, ...args)、proxy.apply(...)
- 13、construct(target, args):拦截 Proxy 实例作为构造函数调用的操作,比如new proxy(...args)
总共 13 个拦截方法,下面进行简要举例说明,更多可见阮一峰老师的 《ECMAScript 6 入门》(https://es6.ruanyifeng.com/#docs/proxy)
1、get方法和set方法
get方法用于拦截某个属性的读取操作,可以接受三个参数,依次为目标对象、属性名和 proxy 实例本身(严格地说,是操作行为所针对的对象),其中最后一个参数可选。
set拦截 target 属性的设置,可以接受四个参数,依次为目标对象、属性名、value和 proxy 实例本身(严格地说,是操作行为所针对的对象),其中最后一个参数可选。
let target = {foo: 1}
let proxy = new Proxy(target, {
get(target, key, receiver) {
console.log(`getter ${key}!`)
return target[key]
},
set: function(target, key, value, receiver) {
console.log(`setter ${key}!`)
target[key] = value;
}
})
let obj = Object.create(proxy)
console.log(obj.foo)
// getter foo!
// 1
2、has方法
拦截 propKey in proxy 的操作,返回一个布尔值。
// 使用 has 方法隐藏某些属性,不被 in 运算符发现
var handler = {
has (target, key) {
if (key.startsWith('_')) {
return false;
}
return key in target;
}
};
var foo = { _name: 'saucxs', name: 'saucxs' };
var proxy = new Proxy(foo, handler);
console.log('_name' in proxy); // false
console.log('name' in proxy); // true
3、ownKeys方法
拦截自身属性的读取操作。并返回目标对象所有自身属性的属性名数组。具体返回结果可结合 MDN 属性的可枚举性和所有权
- Object.getOwnPropertyName(proxy)
- Object.getOwnPropertySymbols(proxy)
- Object.keys(proxy)
- for ... in循环
let target = {
_foo: 'foo',
_bar: 'bar',
name: 'saucxs'
};
let handler = {
ownKeys (target) {
return Reflect.ownKeys(target).filter(key => key.startsWith('_'));
}
};
let proxy = new Proxy(target, handler);
for (let key of Object.keys(proxy)) {
console.log(target[key]);
}
// "saucxs"
4、apply方法
apply 拦截 Proxy 实例作为函数调用的操作,比如函数的调用(proxy(...args))、call(proxy.call(object, ...args))、apply(proxy.apply(...))等。
var target = function () { return 'I am the target'; };
var handler = {
apply: function () {
return 'I am the saucxs proxy';
}
};
var proxy = new Proxy(target, handler);
proxy();
// "I am the saucxs proxy"
更多可见阮一峰老师的 《ECMAScript 6 入门》(https://es6.ruanyifeng.com/#docs/proxy)
谢谢支持
1、文章喜欢的话可以「分享,点赞,在看」三连哦。
2、作者昵称:saucxs,songEagle,松宝写代码。「松宝写代码」公众号作者,每日一题,实验室等。一个爱好折腾,致力于全栈,正在努力成长的字节跳动工程师,星辰大海,未来可期。内推字节跳动各个部门各个岗位。
3、长按下面图片,关注「松宝写代码」,是获取开发知识体系构建,精选文章,项目实战,实验室,每日一道面试题,进阶学习,思考职业发展,涉及到JavaScript,Node,Vue,React,浏览器,http等领域,希望可以帮助到你,我们一起成长~

字节内推福利
- 回复「校招」获取内推码
- 回复「社招」获取内推
- 回复「实习生」获取内推
后续会有更多福利
学习资料福利
回复「算法」获取算法学习资料
往期「每日一题」
1、JavaScript && ES6
第 16 题:【每日一题】面试官问:JS中如何全面进行客户端检测?
第 15 题:【每日一题】面试官问:JS类型判断有哪几种方法?
第 14 题:【每日一题】面试官问:谈谈你对JS对象的创建和引申
第 12 题[每日一题]面试官问:JS引擎的执行过程(二)
第 11 题[每日一题]面试官问:JS引擎的执行过程(一)
第 10 题[每日一题]面试官问:详细说一下JS数据类型
2、浏览器
3、Vue
4、算法
5、Http
[每日一题]面试官问:谈谈你对ES6的proxy的理解?的更多相关文章
- [每日一题]面试官问:for in和for of 的区别和原理?
关注「松宝写代码」,精选好文,每日一题 时间永远是自己的 每分每秒也都是为自己的将来铺垫和增值 作者:saucxs | songEagle 一.前言 2020.12.23 日刚立的 flag,每日一 ...
- [每日一题]面试官问:Async/Await 如何通过同步的方式实现异步?
关注「松宝写代码」,精选好文,每日一题 时间永远是自己的 每分每秒也都是为自己的将来铺垫和增值 作者:saucxs | songEagle 一.前言 2020.12.23 日刚立的 flag,每日一 ...
- 【搞定面试官】谈谈你对JDK中Executor的理解?
## 前言 随着当今处理器计算能力愈发强大,可用的核心数量越来越多,各个应用对其实现更高吞吐量的需求的不断增长,多线程 API 变得非常流行.在此背景下,Java自JDK1.5 提供了自己的多线程框架 ...
- 【MySQL】面试官:谈谈你对Mysql的MVCC的理解?
MVCC(Mutil-Version Concurrency Control),就是多版本并发控制.MVCC 是一种并发控制的方法,一般在数据库管理系统中,实现对数据库的并发访问. 在Mysql的In ...
- 「每日一题」有人上次在dy面试,面试官问我:vue数据绑定的实现原理。你说我该如何回答?
关注「松宝写代码」,精选好文,每日一题 时间永远是自己的 每分每秒也都是为自己的将来铺垫和增值 作者:saucxs | songEagle 来源:原创 一.前言 文章首发在「松宝写代码」 2020. ...
- 每日一问:面试结束时面试官问"你有什么问题需要问我呢",该如何回答?
面试结束时面试官问"你有什么问题需要问我呢",该如何回答?
- 面试官问,说一个你在工作非常有价值的bug
如果你去参考面试,做足了准备,面对面试官员从容不迫,吐沫横飞的大谈自己的工作经历.突然,面试官横插一句:说一个你在工作非常有价值的bug.顿时,整个空气都仿佛都凝固了!“What?”... 我想没几个 ...
- 面试官问:JS的this指向
前言 面试官出很多考题,基本都会变着方式来考察this指向,看候选人对JS基础知识是否扎实.读者可以先拉到底部看总结,再谷歌(或各技术平台)搜索几篇类似文章,看笔者写的文章和别人有什么不同(欢迎在评论 ...
- 被面试官问懵:TCP 四次挥手收到乱序的 FIN 包会如何处理?
摘要:收到个读者的问题,他在面试的时候,被搞懵了,因为面试官问了他这么一个网络问题. 本文分享自华为云社区<TCP 四次挥手收到乱序的 FIN 包会如何处理?>,作者:小林coding . ...
随机推荐
- 第 4篇 Scrum 冲刺博客
一.站立式会议 1.站立式会议照片 2.昨天已完成的工作 登录信息的匹配 3.今天计划完成的工作 ①售货员页面功能 ②销售排行 4.工作中遇到的困难 ①页面按钮太过复杂,逻辑错乱 ②有的同学数据库驱动 ...
- 实现一个类型判断函数,需要鉴别出基本类型、function、null、NaN、数组、对象?
只需要鉴别这些类型那么使用typeof即可,要鉴别null先判断双等判断是否为null,之后使用typeof判断,如果是obejct的话,再用Array.isArray判断是否为数组,如果是数字再使用 ...
- 【题解】CIRU - The area of the union of circles [SP8073] \ 圆的面积并 [Bzoj2178]
[题解]CIRU - The area of the union of circles [SP8073] \ 圆的面积并 [Bzoj2178] 传送门: \(\text{CIRU - The area ...
- Codeforces Edu Round 66 A-E
A. From Hero to Zero 通过取余快速运行第一步即可.由于\(a \% b (a >= b) <= \frac{a}{2}\).所以总复杂度不超过\(O(log_2n)\) ...
- HDU3686 Traffic Real Time Query System
P.S.此题无代码,只有口胡,因为作者码炸了. 题目大意 给你一个有 \(n\) 个点, \(m\) 条边的无向图,进行 \(q\) 次询问,每次询问两个点 \(u\) \(v\),输出两个点的之间的 ...
- 【APIO2018】选圆圈(平面分块 | CDQ分治 | KDT)
Description 给定平面上的 \(n\) 个圆,用三个参数 \((x, y, R)\) 表示圆心坐标和半径. 每次选取最大的一个尚未被删除的圆删除,并同时删除所有与其相切或相交的圆. 最后输出 ...
- 算法—— n个骰子的点数
把n个骰子扔在地上,所有骰子朝上一面的点数之和为s.输入n,打印出s的所有可能的值出现的概率. 你需要用一个浮点数数组返回答案,其中第 i 个元素代表这 n 个骰子所能掷出的点数集合中第 i 小的那个 ...
- [打基础]一些C++自带的库(持续更新)
iomanip manip是manipulator(嗯,操作器?)的缩写,对应头文件就是 #include<iomanip> 在算法竞赛里用得到的应该是两个接口:进制转换(8,10,16) ...
- [日常摸鱼]HDU1724 Ellipse-自适应Simpson法
模板题~ QAQ话说Simpson法的原理我还是不太懂-如果有懂的dalao麻烦告诉我~ 题意:每次给一个椭圆的标准方程,求夹在直线$x=l$和$x=r$之间的面积 Simpson法 (好像有时候也被 ...
- DRF类视图让你的代码DRY起来
刚开始写views.py模块的代码,一般都是用def定义的函数视图,不过DRF更推荐使用class定义的类视图,这能让我们的代码更符合DRY(Don't Repeat Yourself)设计原则: 使 ...