学习 vue2.0/3.0 中的proxy和Object.defineProperty 小记

  vue3.0将双向数据绑定的主要方法从Object.defineProperty舍弃,使用了proxy的方式通过观察者模式实现相关的数据变化监听,总的来说是一个很好地前进。今天简单的实验了一下相关的实现和不同情况下的使用输出。简单记录一下吧。同时说明代码中是使用数组的例子进行区分的。

  个人认为proxy的实现方式要比Object.defineProperty优雅很多,Object.defineProperty首先是指数据劫持,实际上proxy的运行是后置于Object.defineProperty,也就是说如果对同一个对象进行俩者同时使用的时候,要注意Object.defineProperty的各个参数是否会影响proxy内部的设置,例如configurable属性如果设置了不可修改,那么在proxy进行代理时,在get方法中最终改变了输出的内容,是会出现问题的。

   var data = {}
    Object.defineProperty(data, ‘a‘, {
      value: 1,
      configurable: true,
    })
    let proxy = new Proxy(data, {
      get(obj, prop) {
        console.log(‘get‘);
        return 2;
      },
      set(obj, prop, val) {
        console.log(‘set‘);
        console.log(obj);
        obj[prop]= val;
        return true;
      }
    });
    console.log(proxy.a);

  如果此处的configurable不设置为true则会报错。除此之外Object.defineProperty另外的两个属性也有一些自己的使用方法在其中。使用的时候要注意。

  同时由上面的代码可以明显的看出proxy的方式对对象进行设置代理的时候,会比Object.defineProperty进行劫持的时候方便很多,因为Object.defineProperty需要对具体的某个属性进行设置,这就导致了我们需要遍历所有的对象内部的内容,之后对每个都进行劫持才可以达到想要的效果,而proxy仅仅对对象整体进行监控就好了。

  除此之外proxy也增加了对于数组的监控。

var data = {
  dataarr: [1,2,3,4]
};
let proxy = new Proxy(data.dataarr, {
  get(obj, prop) {
    return obj[prop];
  },
  set(obj, prop, val) {
    console.log(‘set‘);
    obj[prop]= val;
    return true;
  }
});
proxy.push(1);
console.log(data.dataarr);
// set
// [1, 2, 3, 4, 1]

  此时在上面代码中,如果添加了对应的数组内容。proxy会提示数组发生了变化。同样的,使用诸如proxy[1] = 7等等都可以触发更改,而Object.defineProperty则不同,它并不能在修改数组内容时触发相应的更改。

var data = {};
var watch;
Object.defineProperty(data, ‘dataarr‘, {
  set(val) {
    console.log(‘set‘);
    watch = val;
    return true;
  },
  get() {
    console.log(‘get‘);
    return watch;
  }
})
data.dataarr = [1,2,3,4];
data.dataarr.push(3);
// set
// get

  我们可以看到实际上第一个set是由你设置data.dataarr = [1,2,3,4]; 触发产生的。而push操作实际上仅仅是修改了data.dataarr的内容,并没有触发set。

  但是但是。proxy虽然很好用,但是它的性能其实很差。差到什么地步呢?假设我们按照如下代码检测。

var _obj = {};
var proxy = new Proxy(_obj, {
  set: (obj, prop, value) => { _obj[prop] = value; }
});

var defineProp = {};
Object.defineProperty(defineProp, ‘prop‘, {
  configurable: false,
  set: v => defineProp._v = v
});

//  上述为建立不同的对象

obj.prop = 5;

proxy.prop = 5;

defineProp.prop = 5;

// 为赋值语句。

  如果我们按照这样的逻辑进行赋值代码,最终实现的监测数据是这样的

vanilla x 74,288,023 ops/sec ±0.78% (86 runs sampled)
proxy x 3,625,152 ops/sec ±2.51% (86 runs sampled)
defineProperty x 74,815,513 ops/sec ±0.80% (85 runs sampled)
Fastest is defineProperty,vanilla

ps:ops/sec为每秒执行次数,数字越大越好。

  可以看到速度会比defineProperty的方式整整慢了一倍多,如果当然还有其他的情况下的检测,如果有兴趣可以看https://thecodebarbarian.com/thoughts-on-es6-proxies-performance,一位大佬写的检测。但是这就像前面这篇文章结尾说的那样。实际上对于执行速度的慢并不能影响proxy的推行,就例如promise的执行效率实际上要比回调的方式慢好多,但是依旧无法阻挡它推行的脚步,而且据一些国内大佬的检测数据来看,在较新版本下的node运行promise已经比以前的速度要快了很多,也就是说其实技术的优化始终可以达到。我们要的首先都是要好,只要性能不会太限制使用就好。人们一起推进的力量是伟大的。总会优化到我们欣喜的模样。vue3.0或许是一个很好的契机。借助vue3.0的推行,proxy的未来相信会越来越好。

原文地址:https://www.cnblogs.com/acefeng/p/12222552.html

时间: 2024-10-13 05:20:02

学习 vue2.0/3.0 中的proxy和Object.defineProperty 小记的相关文章

vue中实现双向数据绑定原理,使用了Object.defineproperty()方法,方法简单

在vue中双向数据绑定原理,我们一般都是用v-model来实现的 ,但一般在面试话会问到其实现的原理, 方法比较简单,就是利用了es5中的一个方法.Object.defineproperty(),它有三个参数, Object.defineproperty(obj,'val',attrObject), 参数1: obj是属性所在的对象,参数2: 'val',属性名,它是一个string类型,参数3: {}属性所描述的对象 详情可以看Object.defineproperty的文档 下面直接上dem

学习vue2.0

学习vue2.0总结: 一.基础 1.局部组件与全局组件: 全局组件:Vue.compotent(组件名,options),参考网址:http://www.cnblogs.com/yesyes/p/6658611.html 局部组件:export default {compotents: {组件名[:组件实例]}} 2.一个组件被某一组件引用多次??? 3.props: props 是单向绑定的:当父组件的属性变化时,将传导给子组件,但是不会反过来.这是为了防止子组件无意修改了父组件的状态--这

vue2.0在table中实现全选和反选

其实在去年小颖已经写过一篇:Vue.js实现checkbox的全选和反选 小颖今天在跟着慕课网学习vue的过程中,顺便试试如何在table中实现全选和反选,页面的css样式是直接参考慕课网的样式写的,js是小颖自己写哒,欢迎大家吐槽和点赞,嘻嘻 慕课网demo的  git 地址:ShoppingCart 页面效果: 具体怎么实现的呢? 因为上篇文章:使用localstorage来存储页面信息 中已经有写项目是怎么创建的所以小颖在这里就不重复了,其实只是在上篇文章的基础上稍微做了改动: App.v

0. Java开发中的23种设计模式详解(转)

设计模式(Design Patterns) ——可复用面向对象软件的基础 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了可重用代码.让代码更容易被他人理解.保证代码可靠性. 毫无疑问,设计模式于己于他人于系统都是多赢的,设计模式使代码编制真正工程化,设计模式是软件工程的基石,如同大厦的一块块砖石一样.项目中合理的运用设计模式可以完美的解决很多问题,每种模式在现在中都有相应的原理来与之对应,每一个模式描述了一个在我们周

NVIDIA DIGITS 学习笔记(NVIDIA DIGITS-2.0 + Ubuntu 14.04 + CUDA 7.0 + cuDNN 7.0 + Caffe 0.13.0)

转自:http://blog.csdn.net/enjoyyl/article/details/47397505?from=timeline&isappinstalled=0#10006-weixin-1-52626-6b3bffd01fdde4900130bc5a2751b6d1 NVIDIA DIGITS-2.0 + Ubuntu 14.04 + CUDA 7.0 + cuDNN 7.0 + Caffe 0.13.0环境配置 引言 DIGITS简介 DIGITS特性 资源信息 说明 DIGI

基于Cocos2d-x学习OpenGL ES 2.0系列——编写自己的shader(2)

在上篇文章中,我给大家介绍了如何在Cocos2d-x里面绘制一个三角形,当时我们使用的是Cocos2d-x引擎自带的shader和一些辅助函数.在本文中,我将演示一下如何编写自己的shader,同时,我们还会介绍VBO(顶点缓冲区对象)和VAO(顶点数组对象)的基本用法. 在编写自己的shader之前,我觉得有必要提一下OpenGL渲染管线. 理解OpenGL渲染管线,对于学习OpenGL非常重要.下面是OpenGL渲染管线的示意图:(图中淡蓝色区域是可以编程的阶段) 此图是从wiki中拿过来的

Retrofit2.0通俗易懂的学习姿势,Retrofit2.0 + OkHttp3 + Gson + RxJava

Retrofit2.0通俗易懂的学习姿势,Retrofit2.0 + OkHttp3 + Gson + RxJava Retrofit,因为其简单与出色的性能,也是受到很多人的青睐,但是他和以往的通信框架还是有点区别,不过放心,因为他本身还是挺简单的,所有我相信你看完这篇文章,对基本的请求是没什么问题的,其实现在网上这样的文章也有很多了,好了,那我们直接开车吧! 一.相关资料 Github:https://github.com/square/retrofit 官网文档:http://square

IOS学习之蓝牙4.0

转载请注明出处 作者:小马 IOS学习也一段时间了,该上点干货了.前段时间研究了一下IOS蓝牙通讯相关的东西,把研究的一个成果给大家分享一下. 一 项目背景 简单介绍一下做的东西,设备是一个金融刷卡器,通过蓝牙与iphone手机通讯.手机端的app通过发送不同的指令(通过蓝牙)控制刷卡器执行一些动作,比如读磁条卡,读金融ic卡等.上几张图容易理解一些:              看了上面几张图,你应该大概了解这是个什么东东了. 二 IOS 蓝牙介绍 蓝牙协议本身经历了从1.0到4.0的升级演变,

Log4j 2.0在开发中的高级使用详解—配置简单的文件输出(四)

在log4j 1.x的版本中,我们想将日志输出的文件中,需要很复杂的配置.这点已经在2.0的版本中得到了大大的改善. 简单的配置,以及灵活的应用,已经成为了一种趋势.不管我们以追加的形式写日志文件,还是覆盖的形式,配置他们都是小菜. 还有比如日志文件大小自动分割,自动备份,无死锁,高性能等等.更令人欣喜的是,它支持json格式的配置,加载快,轻巧,异步读写. 好吧,来看它的使用吧. 看配置文件log4j2.xml代码: <?xml version="1.0" encoding=&