双向绑定Proxy VS Object.defineProperty
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.foo
和proxy['foo']
。 - set(target, propKey, value, receiver):拦截对象属性的设置,比如
proxy.foo = v
或proxy['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的更多相关文章
- 【Vue】-- 数据双向绑定的原理 --Object.defineProperty()
Object.defineProperty()方法被许多现代前端框架(如Vue.js,React.js)用于数据双向绑定的实现,当我们在框架Model层设置data时,框架将会通过Object.def ...
- MVVM双向绑定实现之Object.defineProperty
随着web应用的发展,直接操作dom的应用已渐行渐远,取而代之的是时下越来越流行的MVVM框架,dom操作几乎绝迹,这里面自然是框架底层封装的结果.MVVM框架的双向数据绑定使开发效率大大提高:然后在 ...
- 实现双向绑定Proxy比defineproperty优劣如何?
前言 双向绑定其实已经是一个老掉牙的问题了,只要涉及到MVVM框架就不得不谈的知识点,但它毕竟是Vue的三要素之一. Vue三要素 响应式: 例如如何监听数据变化,其中的实现方法就是我们提到的双向绑定 ...
- vue实现双向绑定的简单原理: defineProperty
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- vue双向数据绑定的原理-object.defineProperty() 用法
有关双向数据绑定的原理 关于数据双向绑定的理解:利用了 Object.defineProperty() 这个方法重新给对象定义了新属性,在操作新属性分别为为获取属性值(调用get方法)和设置属性值(调 ...
- 双向数据绑定实现之Object.defineProperty
vue.js利用的是es5的 defineproperty 特性实现的双向数据绑定,了解一下基本原理. 举例 var person= {}; Object.defineProperty(person, ...
- vuejs的双向数据绑定实现原理——object.defineproperty()
视图和数据变化绑定 而vue.js主要利用了accessor descriptors的set和get来更新视图,这里看到的这个例子挺好,是一个简单的绑定.对于一个html页面 <div> ...
- 浅谈Vue之双向绑定
VUE实现双向数据绑定的原理就是利用了 Object.defineProperty() 这个方法重新定义了对象获取属性值(get)和设置属性值(set)的操作来实现的.那么Object.defineP ...
- Vue2.0实现双向绑定的原理
一.几种实现双向绑定的做法 目前几种主流的mvc(vm)框架都实现了单向数据绑定,而我所理解的双向数据绑定无非就是在单向绑定的基础上给可输入元素(input.textare等)添加了change(in ...
随机推荐
- playbooks框架部署远程主机
进入到ansible和python环境 进入python3.6虚拟环境 #su - deploy #source .py3-a2.5-env/bin/activate 加载ansible 2.5版本 ...
- Matplotlib从兴趣到实践
先看下Matplotlib实现的效果 是不是出现了也想敲一个的心动,那让我们一起来了解Matplotlib吧 Matplotlib安装 1.Windows系统安装Matplotlib 进入到cmd的命 ...
- 提高Dom 访问效率
在浏览器中对于Dom的操作和普通的脚本的操作处于两个不同的dll中,两个dll的交互是比较耗时的,优化对Dom的操作可以提高脚本的执行速度. JS访问DOM是很慢的,尽量不要用JS来设置页面 布局 有 ...
- 《前端之路》--- 重温 Koa2
目录 一.简单介绍 二. 路由 三.请求数据 四. 静态资源加载 五. 静态资源加载 六. koa2加载模板引擎 七. koa2 中简单使用 mysql 数据库 八. koa2 中使用单元检测 九. ...
- Liunx(centos8)下的yum的基本用法和实例
yum 命令 Yum(全称为 Yellow dog Updater, Modified)是一个在Fedora和RedHat以及CentOS中的Shell前端软件包管理器.基于RPM包管理,能够从指定的 ...
- Flask 笔记
1.CBV 模式 1.继承 views.MethodView from flask.views import MethodView 2.HTTP具有 8 种请求方法 - CBV中的方法 - GET 获 ...
- openresty http
openresty http openresty默认没有提供http客户端,需要第三方提供插件. 下载方式: wget https://raw.githubusercontent.com/pintsi ...
- mysql--->B+tree索引的设计原理
1.什么是数据库的索引 每种查找算法都只能应用于特定的数据结构之上,例如二分查找要求被检索数据有序,而二叉树查找只能应用于二叉查找树上,但是数据本身的组织结构不可能完全满足各种数据结构(例如,理论上不 ...
- SparkSQL 如何自定义函数
1. SparkSql如何自定义函数 2. 示例:Average 3. 类型安全的自定义函数 1. SparkSql如何自定义函数? spark中我们定义一个函数,需要继承 UserDefinedAg ...
- [Ubuntu]解决"系统的网络服务与此版本的网络管理器不兼容"提示
先贴方法: sudo -s ' 获取root权限 apt-get install network-manager ' 重装网络管理器 如果系统提示有升级包可用则安装即可. 开机后,右上角没有网络图标. ...