当前位置: 首页 > 工具软件 > jsproxy > 使用案例 >

js的Proxy代理的基本使用

丁德义
2023-12-01

vue2.0是的数据响应式是基于Object.defineProperty的方式来实现的,到了vue3.0,尤雨溪就把它改成用Proxy代理的方式来实现数据响应式。
Proxy的定义:代理的意思。就是你想要对数据进行操作,必须经过代理,让代理去帮你操作数据,你只需要对代理发号施令就可以了。相当于Proxy就是你的管家,你想买什么吃的,就跟管家说,管家会帮你去买。

使用Proxy:

const target = {
	name: 'wjg',
	age: 18
}
const proxy = new Proxy(target, {
	get(target,prop) {
		console.log('Get Value: ' + target[prop])
		return target[prop]
		// return target[prop] 等价于: return Reflect.get(target,prop)
	},
	set(target, prop, value) {
		console.log('Set prop: ' + prop + ' to value:' + value)
		target[prop] = value
		// target[prop] = value 等价于: Reflect.set(target, prop, value)
	}
})
console.log(proxy.name)
proxy.age = 19
console.log(proxy.age)
console.log(target.age)

解释:

  1. Proxy需要传进去两个参数,第一个你要代理的对象;第二个是handler,是你要对数据操作的一些方法。比如:get、set方法等等。
  2. 实例化Proxy会返回一个代理对象。以后我们想要对target这个对象进行操作的时候,就对代理对象proxy进行操作就行了,它会帮我们去操作target对象的。
  3. get方法的形参:第一个参数:要操作的对象;第二个参数:是你要操作的属性名。
  4. set方法的形参:第一和第二都和get方法的一样。第三个是你要设置的新的值。
  5. Reflect::映射。就是将对象的方法映射到Reflect这个对象。由于target[prop] = value这个操作有可能产生异常,而使用Reflect.set(target, prop, value)这个函数调用,它内部会帮我们try catch,操作失败它会返回一个fasle,就不至于导致程序异常。

与Object.defineProperty的区别:

  1. 都能够实现数据劫持
  2. Object.defineProperty是在原对象上进行数据劫持,而Proxy是对它返回的代理对象上进行数据劫持。

重写Proxy:

function deepClone(target) {
	if(typeof target  !== 'object' || target === null) {
		return target
	}
	const res = target instanceof Array ? [] : {}
	for(let key in target) {
		if(target.hasOwnProperty(key)) {
			if(typeof target[key] === 'object' && target[key] !== null ) {
				res[key] = deepClone(target[key])
			} else {
				res[key] = target[key]
			}
		}
	} 
	return res
}
function MyProxy(target, handler) {
	const _target = deepClone(target)
	Object.keys(_target).forEach(item => {
		Object.defineProperty(_target, item, {
			get() {
				return handler.get && handler.get(target, item)
			},
			set(newVal) {
				handler.set && handler.set(target, item, newVal)
			}
		})
	})
	return _target
}
const target = {
	name: 'wjg',
	age: 18
}
const proxy = new MyProxy(target, {
	get(target, prop) {
		console.log('Get Value: ' + target[prop])
		return target[prop]
	},
	set(target, prop, value) {
		console.log('Set prop: ' + prop + ' to value:' + value)
		target[prop] = value
	}
})
console.log(proxy.name)
proxy.age = 19
console.log(proxy.age)
console.log(target.age)

实现原理:

  1. 由于Proxy不是对原对象进行操作的,所以我们需要对目标对象进行深拷贝。
  2. 深拷贝完对拷贝完的对象的每一个属性进行重新定义,使用Object.defineProperty来操作。
  3. 在get方法中调用handler.get方法,但是传进去的是原对象target,set也是。所以就是我们操作代理里对象,让代理对象来帮我们去操作原对象。
  4. 记得返回被克隆的target对象
 类似资料: