Vue3.0的双向绑定将使用Proxy代替Object.defineProperty,据尤大说,速度提升了1倍。

本文我们来探讨一下Proxy对比Object.defineProperty究竟有哪些优劣呢?

首先介绍一下什么是Proxy?

Proxy在ES6规范中被正式发布,Proxy可以理解成在目标对象之前架设一层“拦截”,外界对该对象的访问,都必须先通过这层拦截,因此提供了一种机制,可以对外界的访问进行过滤和改写。

Proxy语法:

ES6原生提供Proxy构造函数,用来生成Proxy实例

var proxy = new Proxy(target,handler);

Proxy接受两个参数:

target:要代理目标对象

handler: 处理函数,该函数将拦截对应的操作

下面是 Proxy 支持的拦截操作一览,一共 13 种。

  • get(target, propKey, receiver):拦截对象属性的读取,比如proxy.fooproxy['foo']
  • set(target, propKey, value, receiver):拦截对象属性的设置,比如proxy.foo = vproxy['foo'] = v,返回一个布尔值。
  • has(target, propKey):拦截propKey in proxy的操作,返回一个布尔值。
  • deleteProperty(target, propKey):拦截delete proxy[propKey]的操作,返回一个布尔值。
  • ownKeys(target):拦截Object.getOwnPropertyNames(proxy)Object.getOwnPropertySymbols(proxy)Object.keys(proxy)for...in循环,返回一个数组。该方法返回目标对象所有自身的属性的属性名,而Object.keys()的返回结果仅包括目标对象自身的可遍历属性。
  • getOwnPropertyDescriptor(target, propKey):拦截Object.getOwnPropertyDescriptor(proxy, propKey),返回属性的描述对象。
  • defineProperty(target, propKey, propDesc):拦截Object.defineProperty(proxy, propKey, propDesc)Object.defineProperties(proxy, propDescs),返回一个布尔值。
  • preventExtensions(target):拦截Object.preventExtensions(proxy),返回一个布尔值。
  • getPrototypeOf(target):拦截Object.getPrototypeOf(proxy),返回一个对象。
  • isExtensible(target):拦截Object.isExtensible(proxy),返回一个布尔值。
  • setPrototypeOf(target, proto):拦截Object.setPrototypeOf(proxy, proto),返回一个布尔值。如果目标对象是函数,那么还有两种额外操作可以拦截。
  • apply(target, object, args):拦截 Proxy 实例作为函数调用的操作,比如proxy(...args)proxy.call(object, ...args)proxy.apply(...)
  • construct(target, args):拦截 Proxy 实例作为构造函数调用的操作,比如new proxy(...args)

下面介绍两个常用的拦截方法:get方法和set方法。

//get方法用于拦截某个属性的读取操作
//接受三个参数,依次为目标对象、属性名和Proxy实例本身,最后一个参数可选 //set方法用于拦截某个属性的赋值操作
//接受四个参数,一次为目标对象、属性名、属性值和Proxy实例本身,最后一个参数可选 var person = {
  name:'Jack',
  age:20
};
var handler = {
  get(target,key){
    if(key in target){
      console.log(`${key}被读取`);
      return target[key]
    }else{
      throw new ReferenceError(`Property ${key} does not exist`)
    }
  },
  set(target,key,value){
    console.log(`${key}被设置为${value}`)
    target[key] = value
  }
};
let instance = new Proxy(person,handler);
instance.name //name被读取
instance.age = 25 //age被设置为25

Object.defineProperty缺点:

1. 对数组的支持不好,无法监听到数组的变化,在Vue官方文档说明了可以监听到数组的变动,但只限于push、pop、shift、unshift、splice、sort、reverse方法。实际上是他们对这几种方法进行了重写。

var arrayProto = Array.prototype;
var arrayMethods = Object.create(arrayProto);
[
'push',
'pop',
'shift',
'unshift',
'splice',
'sort',
'reverse'
].forEach(function(item){
Object.defineProperty(arrayMethods,item,{
value:function mutator(){
//缓存原生方法,之后调用
  console.log('array被访问');
  var original = arrayProto[item]
  var args = Array.from(arguments)
     original.apply(this,args)
// console.log(this);
},
})
})

2.Object.defineProperty监听的是对象的属性,当一个对象为深层嵌套的时候,必须进行递归遍历,比较麻烦。

  

Proxy对比Object.defineProperty:

优点:

  1. Proxy可以劫持整个对象,这样以来操作便利程度远远优于Object.defineProperty。

  2. Proxy可以直接监听数组的变化,无需进行数组方法重写。

var arr = [1,2,3,4];
  var instance = new Proxy(arr,{
  get(target,key){
  console.log('数组被读取')
  return Reflect.get(target,key)
},
set(target,key,val){
  console.log('监听到数组更新')
  return Reflect.set(target,key,val)
}
}) instance[0] = 5 //监听到数组更新
instance.push(6) //数组被读取 监听到数组更新

  3. Proxy支持13种拦截操作,是Object.defineProperty不具备的。

缺点:Proxy的兼容性不是太好,不兼容IE,且无法通过polyfill提供兼容。 

 

双向绑定Proxy VS Object.defineProperty的更多相关文章

  1. 【Vue】-- 数据双向绑定的原理 --Object.defineProperty()

    Object.defineProperty()方法被许多现代前端框架(如Vue.js,React.js)用于数据双向绑定的实现,当我们在框架Model层设置data时,框架将会通过Object.def ...

  2. MVVM双向绑定实现之Object.defineProperty

    随着web应用的发展,直接操作dom的应用已渐行渐远,取而代之的是时下越来越流行的MVVM框架,dom操作几乎绝迹,这里面自然是框架底层封装的结果.MVVM框架的双向数据绑定使开发效率大大提高:然后在 ...

  3. 实现双向绑定Proxy比defineproperty优劣如何?

    前言 双向绑定其实已经是一个老掉牙的问题了,只要涉及到MVVM框架就不得不谈的知识点,但它毕竟是Vue的三要素之一. Vue三要素 响应式: 例如如何监听数据变化,其中的实现方法就是我们提到的双向绑定 ...

  4. vue实现双向绑定的简单原理: defineProperty

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  5. vue双向数据绑定的原理-object.defineProperty() 用法

    有关双向数据绑定的原理 关于数据双向绑定的理解:利用了 Object.defineProperty() 这个方法重新给对象定义了新属性,在操作新属性分别为为获取属性值(调用get方法)和设置属性值(调 ...

  6. 双向数据绑定实现之Object.defineProperty

    vue.js利用的是es5的 defineproperty 特性实现的双向数据绑定,了解一下基本原理. 举例 var person= {}; Object.defineProperty(person, ...

  7. vuejs的双向数据绑定实现原理——object.defineproperty()

    视图和数据变化绑定 而vue.js主要利用了accessor descriptors的set和get来更新视图,这里看到的这个例子挺好,是一个简单的绑定.对于一个html页面 <div> ...

  8. 浅谈Vue之双向绑定

    VUE实现双向数据绑定的原理就是利用了 Object.defineProperty() 这个方法重新定义了对象获取属性值(get)和设置属性值(set)的操作来实现的.那么Object.defineP ...

  9. Vue2.0实现双向绑定的原理

    一.几种实现双向绑定的做法 目前几种主流的mvc(vm)框架都实现了单向数据绑定,而我所理解的双向数据绑定无非就是在单向绑定的基础上给可输入元素(input.textare等)添加了change(in ...

随机推荐

  1. macOS 10.11.* 安装scrapy

    1.安装brew,然后修改brew源为某高校 2.更新python brew install python 3.安装pip 4.安装scrapy,这里肯定会有一个坑,之前在网上看到10.11开启了什么 ...

  2. 网鼎杯题目“phone”--十六进制mysql注入

    注册后,即可点击查看谁的电话和我类似. 注册时有三个必填项,分别是用户名.密码和电话.电话要求必须数字. 注册个1111的电话后,点击查看,返回有1个人电话和我类似,在注册一个为1111的,返回有2人 ...

  3. Educational Codeforces Round 80 (Rated for Div. 2) E. Messenger Simulator

    可以推出 min[i]要么是i要么是1,当a序列中存在这个数是1 max[i]的话就比较麻烦了 首先对于i来说,如果还没有被提到第一位的话,他的max可由他后面的这部分序列中 j>=i 的不同数 ...

  4. Ubuntu16手动安装OpenStack——glance篇--转

    全文转自https://www.voidking.com/dev-ubuntu16-manual-openstack-glance/ 目标 紧接着<Ubuntu16手动安装OpenStack—— ...

  5. Java容器解析系列(11) HashMap 详解

    本篇我们来介绍一个最常用的Map结构--HashMap 关于HashMap,关于其基本原理,网上对其进行讲解的博客非常多,且很多都写的比较好,所以.... 这里直接贴上地址: 关于hash算法: Ha ...

  6. Django orm常用字段和字段参数

    1.Object Relational Mapping(ORM) 1.1ORM介绍 ORM概念 对象关系映射(Object Relational Mapping,简称ORM)模式是一种为了解决面向对象 ...

  7. Jpofiler

    参考链接: https://blog.csdn.net/u010638673/article/details/81703942

  8. 二、Django学习之增删改查

    增加数据 第一种方式 def index(request): #创建记录方式1 #实例化要添加的记录(对象) student_obj = models.Student( name='dazhuang' ...

  9. 使用Qt自动注册Lav

    Qt播放视频使用QMediaPlayer要注册Lav解码器,如果手动去注册,每次去使用管理员运行命令或者生成.bat文件都比较麻烦. 解决方法步骤如下: 一:编写注册Lav解码器脚本,并取消控制台的显 ...

  10. 设计模式-05建造者模式(Builder Pattern)

    1.模式动机 比如我们要组装一台电脑,都知道电脑是由 CPU.主板.内存.硬盘.显卡.机箱.显示器.键盘和鼠标组成,其中非常重要的一点就是这些硬件都是可以灵活选择,但是组装步骤都是大同小异(可以组一个 ...