编辑代码



//proxy应用于vue3.x版本 vue2.x使用object.defineProperty对数据劫持,
//原因是object.defineProperty
//1.无法监听原生数组的变化,需补充数组的处理方式
//2.必须遍历每个属性(实例初始化时,从根节点遍历到末节点,将其每个data的属性转化为getter、setter,后期添加的属性是无法监听到的因为没有经过Object.defineProperty,一次性遍历)
//3.无法监听到属性的新增和删除,故Vue提供了vue.set、vue.delete去监听新增删除操作

var person = { name: '胡歌', obj: { name: 'obj' } };
//proxy 用于操作对象的默认行为,监听对象的新增删除改变 (set/get/apply/construct/has)
//Proxy可以监听数组;可监听新增删除属性;可深层遍历嵌套的属性;可监听整个对象不需要遍历每一个属性
var personProxy = new Proxy(person, {
    get: (target, key) => {
        console.log('getter');
        return target[key];
    },
    set: (target, key, value) => {
        console.log('setter');
        //Reflect.set Reflect本身是一个对象,是es6新增的操作对象的api ,
        //13个静态方法 (Reflect.set/Reflect.get/Reflect.defineproperty等等)
        //Reflect.defineproperty与object.defineproperty的区别:object.defineproperty出现错误时只能由try/catch捕获,Reflect.defineProperty出现错误返回booblean值false
        return Reflect.set(target, key, value);
    },
    has: (target, key) => {
        console.log(target);
        console.log(key);
    }
});
// console.log(personProxy.name); //getter
// personProxy.name = '李逍遥'; //setrer
personProxy.age = '30';  //setter
delete personProxy.name;
console.log('name' in personProxy); //false
personProxy.obj.name; //getter  


//Object.defineProperty
//只能一次性的定义某一个属性,需遍历data后定义每一个属性
var personNew = {}; //第二个参数是属性名称,必填,针对数组无法去定义数组内的元素
var personDefineproperty = Object.defineProperty(personNew, "name", {
    enumerable: true, //可枚举 for..in /Object.keys()
    configurable:false, //true表示该属性可删除,描述符可修改
    //value、writable与set/get不可同时存在
    value:'dddd',
    writable:true, 
    // get() {
    //     console.log('getter');
    //     return bValue;
    // },
    // set(newValue) {
    //     console.log('setter');
    //     bValue = newValue;
    // }
});

personDefineproperty.name = {'a':1,'b':2};
console.log(personDefineproperty.name); //1
console.log(personDefineproperty); //enumerable:false {} 空对象 /true { name: [Getter/Setter] }
// setTimeout(() => {
//     console.log(personDefineproperty); //{} 空对象
// }, 0)
delete personDefineproperty.name; //无法监听到删除属性
console.log(personDefineproperty.name); //configurable:true undefined/configurable:false { a: 1, b: 2 }
//personDefineproperty.age = '12'; //新增的属性无法监听