前言
在我们面试中, 相信大家都被问到过ES6的新特性,那其中有一个就是我们不得不提的Proxy。那ES6提供的Proxy
到底是是用来干嘛的呢?它和defineProperty
对比的优势又是什么呢?下面我就来和大家介绍介绍这个ES6的新特性--Proxy。
Object.defineProperty
在介绍Proxy
之前,我们首先需要来介绍一下Object.defineProperty
。让大家了解了解直接定义或修改对象属性的方法。
Object.defineProperty
它其实是 JavaScript 中用于直接在对象上定义或修改属性的方法。它允许我们对单个属性进行精确的控制,包括设置属性的值、获取属性的值、设置属性的特性等等。使用 Object.defineProperty
我们可以定义对象的属性,并在属性访问或修改时执行自定义逻辑而不执行它本该执行的逻辑。
代码演示如下:
javascript
let obj = {
name: 'zhangsan',
}
let _name = 'lisi';
Object.defineProperty(obj, 'name', {
get: function() {
console.log('获取 name 属性');
return _name
},
set: function( value) {
console.log('设置 name 属性');
_name = value
}
})
console.log(obj.name);//获取
obj.name = 'wanger' // 设置
console.log(obj.name);
如上述代码,我们使用Object.defineProperty
劫持了obj
的 name
属性,同时自定义了逻辑,当我们在获取或设置name
属性时,我们就执行自己自定义后的代码。我们共获取name
属性时,它走get
函数,当我们设置name
属性时,它走set
函数,打印如下:

Proxy
上面我们简单的介绍了一下Object.defineProperty
方法,现在我们再来和大家细讲一下Proxy
方法。
首先,Proxy是JavaScript 中的一个内置对象,它是用于创建一个可以代理目标对象的代理对象。我们可以使用 Proxy
拦截并访问和修改底层对象的操作,从而实现自定义的行为。
通俗一点讲的话,可以将Proxy理解成一种拦截代理机制,它是用来在目标对象之前设置一层拦截
,当我想访问这该对象时,都必须要先通过这层拦截,同时我们可以对外界的访问进行过滤和改写。
它的代码定义如下:
javascript
const proxy = new Proxy(target, handler)
- target: 我们要代理的目标对象
- handler: 我们处理目标对象的处理程序对象,包含拦截对象的一组方法(部分):
get(target, property, receiver)
:拦截对目标对象属性的读取操作。set(target, property, value, receiver)
:拦截对目标对象属性的写入操作。
代码演示如下:
javascript
const target = {
name: 'zhangsan',
age: 25
};
const handler = {
get(target, property, receiver) {
console.log('receiver:', receiver);
console.log(`获取 ${property} 属性`);
return target[property];
},
set(target, property, value, receiver) {
console.log(`设置 ${property} 属性为 ${value}`);
target[property] = value;
return true;
}
};
const proxy = new Proxy(target, handler);
console.log(proxy.name);
proxy.name = 'lisi;
console.log(proxy.name);
console.log(target);
如上述代码, 我们将target
设置成了目标对象,同时写了一个hanler作为处理程序对象,定义了get
和set
方法来拦截等于属性写入和读取的操作。最后,我们使用 Proxy
创建了一个代理对象 proxy
,它代理了目标对象 target
并应用定义的拦截方法去拦截target
的读写操作。

最后经过代码我们的目标对象target
打印结果为:

Proxy强大之处
相比于Object.defineProperty
, Proxy
是一种更高级的代理机制,它可以对整个对象进行拦截和处理,而Object.defineProperty
只能对对象的某个属性进行代理。
通过是Proxy
, 我们可以直接定义handler
对象来拦截并处理对目标对象的各种操作,我们还可以动态的添,移除和修改拦截的逻辑,使我们的代理更加灵活。
与Object.defineProperty
相比,Proxy
的优点有如下几点:
- 完善性:
Proxy
提供了更多广泛的拦截操作选项,拥有更多拦截和自定义的对象操作,例如:函数调用、in操作符、构造函数等。 - 动态性:
Proxy
允许我们动态地添加、移除和修改拦截逻辑,而不仅仅是在对象创建时就定义。 - 简洁性:
Proxy
的用法更简洁明了,不需要像Object.defineProperty
那样在每个属性上进行单独的定义。
Vue3使用Proxy的原因?
我们都知道,在Vue3
中数据响应式的代理机制从Object.defineProperty
换成了Proxy
,那在Vue3
中,使用Proxy代理的主要原因有以下几点:
- 功能更完善:
Proxy
相比于Object.defineProperty
提供了更多的拦截方法。除了get
和set
,还有其他拦截方法,如has
、deleteProperty
、apply
等,可以拦截更多类型的操作。 - 语法更简洁:
Proxy
使用更直观的语法来代理目标对象,并提供了更简洁的代码结构。 - 自动递归监听:
Proxy
可以递归地监听整个对象树结构,不需要像Object.defineProperty
那样需要遍历对象属性进行手动递归监听。 - 性能优化:因为
Proxy
是 JavaScript 引擎的内置特性,它通常比Object.defineProperty
更高效。Proxy
的性能在某些情况下可能会比Object.defineProperty
更优秀。 - 错误处理方便:
Object.defineProperty
在修改不能被修改的对象时会默认失败,而Proxy
可以通过拦截方法来捕获错误并进行相应的处理。