Vue2.x相关Object.defineProperty对于对象劫持和数组响应式实现的一些思考

Posted 码农i

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Vue2.x相关Object.defineProperty对于对象劫持和数组响应式实现的一些思考相关的知识,希望对你有一定的参考价值。

Vue2.x相关Object.defineProperty对于对象劫持和数组响应式实现的一些思考

相信大部分同学都知道,vue2.x大概就是通过Object.defineProperty实现数据劫持,然后结合订阅发布者模式实现响应式,还有不清楚的同学可以去看一下我的另外一篇文章:

Vue双向绑定(数据劫持,发布订阅者模式,diff算法)

同时我们也知道,vue2.x通过defineProperty方法只是劫持了对象,但是对于数组的处理却是通过重写原生方法实现的响应式,那为什么会这样呐?

现在很多的文章都是说defineProperty存在有缺陷,没有办法监听数组的变化,但实际上defineProperty是可以通过数组下标来实现劫持的,毕竟数组对象是一家嘛,下面就是我做的一点验证:

const arr = ['a','b','c','d'];
		function defineReactive(data, key) {
			Object.defineProperty(data, key, {
				get: function() {
					console.log('key:' + key)
				},
				set: function(value) {
					console.log('value:' + value)
				}
			});
		};
		function Observe(data) {
			Object.keys(data).forEach(function(key) {    
				defineReactive(data, key, data[key])  
			})
		};
		Observe(arr);
		
		arr[1];
		arr[2] = '3';

控制台输出如下:
所以说defineProperty本身是可以监控到数组下标的变化的,只是Vue 从通过对性能/体验的性价比考虑放弃了这个特性,defineProperty简直委屈死了。

关于defineProperty实现劫持为什么在性能和体验上不如重写数组方法也有人在github上问过vue的开发者,但是尤雨溪的回答属实太过精炼而我也不知道怎么去比较两者的性能,所以只能硬记了

同样的vue3以上的版本是用了proxy替换了defineProperty,那这又是为什么类?

其实最大的好处就是proxy是对整个对象进行代理,所以可以监听对象某个属性值的变化,还可以监听对象属性的新增和删除,而且还可以监听数组;而 defineProperty 只是给对象的某个已存在的属性添加对应的 getter 和 setter,所以它只能监听这个属性值的变化,而不能去监听对象属性的新增和删除。

但是还有一些文章说还有一部分原因是 proxy在性能上比defineProperty好。可proxy真的比defineProperty性能更好速度更快吗?其实不然,实际上 Proxy 在性能上是要比 Object.defineProperty 差的,详情可以参考 Thoughts on ES6 Proxies Performance 这篇文章,也可以参考掘金博主黄轶大佬的 repo。

总结下来就是defineProperty还是挺好一个方法了,还有就是纸上得来终觉浅,觉知此事要躬行。一定要多看多实践,要有自己的理解和认知,加油!!

以上是关于Vue2.x相关Object.defineProperty对于对象劫持和数组响应式实现的一些思考的主要内容,如果未能解决你的问题,请参考以下文章

vue2.x路由更新问题相关处理方式

Object.keysObject.getOwnPropertyNames区别

Vue2.x相关Object.defineProperty对于对象劫持和数组响应式实现的一些思考

关于对象的一些问题

Vue3.X和Vue2.X相比到底做了哪些更新

关于vue的计算属性以及双向绑定的原理理解(vue2.x)以及vue3.0