ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Object.defineProperty和Proxy的比较

2021-05-08 20:02:09  阅读:147  来源: 互联网

标签:Object let Proxy 数组 defineProperty 属性


Object.defineProperty和Proxy的比较

一.Object.defineProperty 介绍

1.基本用法

Object.defineProperty()的作用就是直接在一个对象上定义一个新属性,或者修改一个已经存在的属性

Object.defineProperty(obj, prop, desc);
//obj 需要定义属性的当前对象
//prop 当前需要定义的属性名
//desc 属性描述符

通过Object.defineProperty()为对象定义属性,有两种形式,且不能混合使用,分别为数据描述符,存取描述符,下面分别描述下两者的区别:
1.数据描述符 --特有的两个属性(value,writable):

const Obj = {}
Object.defineProperty(Obj, 'age', {
   val: 18,
   writable: false ,// 是否可以改变,默认false不可以改变
   enumerable:true ,//是否可枚举
   configrable:true//是否可配置
});
Obj.age=20;
console.log(Obj.age)//undefined,因为writable不能改变

2.存取描述符 (是由 getter、setter 函数功能来描述的属性)

Object.defineProperty(data, key, {
                enumerable: true,
                get() {
                    console.log('劫持了');
                    return val;
                },
                set(newVal) {
                    if (newVal === val) {
                        return;
                    }
                    val = newVal;
                }
            });

2.在vue2.x中的应用

有很多人说Object.defineProperty不能监听数组的变化,这种说法是不严谨的,准确的说是不能监听到数组某些方法的变化。

function Observer(data) {
        for (let key in data) {
            let val = data[key];
            Object.defineProperty(data, key, {
                enumerable: true,
                get() {
                    console.log('数组劫持了');
                    return val;
                },
                set(newVal) {
                    if (newVal === val) {
                        return;
                    }
                    val = newVal;
                }
            });
        }
  }
let arr=['张','王','李','赵']
Observer(arr);
arr.pop()//会触发get函数,控制台会打印「数组劫持了」
arr.push('周');//不会触发,劫持失败

总结:数组的[‘push’, ‘unshift’, ‘splice’, ‘reverse’, ‘sort’, ‘shift’, ‘pop’]这些方法中splice、‘push’、unshift是劫持不到的,在vue2.0源码中,是对数组的这三个方法进行了重写。具体如下:

let arrayProto = Array.prototype;
let newProto = Object.create(arrayProto); 
const arrMethods=['push', 'unshift', 'splice', 'reverse', 'sort', 'shift', 'pop'];
arrMethods.forEach(method => {
    newProto[method] = function(...args) {
        let inserted = null;
        switch (method){
            // args 是一个数组
            case 'push':
                inserted = args;
                break;
            case 'unshift':
                inserted = args;
                break;
            case 'splice': //splice方法有三个参数,第三个参数才是被新增的元素
                inserted = args.slice(2);//slice返回一个新的数组
                break;
        }
        if (inserted) ArrayObserver(inserted);      //因为inserted是一个新的数组项,所以要对数组的新增项重新进行劫持
        arrayProto[method].call(this, ...args);     //调用数组本身对应的方法
    }
})
function observer(obj){
...
    //通过Object.defineProperty进行循环递归绑定
}
function ArrayObserver(obj){ //对数组的新增项进行监控
    obj.forEach(item => {
        observer(item);  
    });
}

二.Proxy 介绍

基本用法

语法:

let p = new Proxy(target, handler);

1.target :需要使用Proxy包装的目标对象(可以是任何类型的对象,包括原生数组,函数,甚至另一个代理)。
2.handler: 一个对象,其属性是当执行一个操作时定义代理的行为的函数(可以理解为某种触发器)。具体的handler相关函数请查阅官网

let arr=['张','王','李','赵']
let testArr = new Proxy(arr, {
        get(target, key) {
            console.log('获取了getter属性');
            return target[key];
        }
});
testArr.push('周') //获取了getter属性

三.Object.defineProperty和Proxy对比

  1. Proxy性能优于Object.defineProperty。 Proxy代理的是整个对象,Object.defineProperty只代理对象上的某个属性,如果是多层嵌套的数据需要循环递归绑定;
  2. 对象上定义新属性时,Proxy可以监听到,Object.defineProperty监听不到,需要借助$set方法;
  3. 数组的某些方法(push、unshift和splice)Object.defineProperty监听不到,Proxy可以监听到;
  4. Proxy在ie浏览器存在兼容性问题

标签:Object,let,Proxy,数组,defineProperty,属性
来源: https://blog.csdn.net/weixin_42682011/article/details/116537012

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有