您的位置:首页 > 移动开发 > Objective-C

双向绑定Proxy VS Object.defineProperty

2019-07-09 11:16 281 查看
原文链接:http://www.cnblogs.com/AIonTheRoad/p/11156123.html

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提供兼容。 

 

 

 

 

 

 

转载于:https://www.cnblogs.com/AIonTheRoad/p/11156123.html

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: