随笔

defineProperty 和 Proxy

defineProperty

该方法允许精确添加或修改对象的属性。通过赋值来添加的普通属性会创建在属性枚举期间显示的属性(for...in 或 Object.keys 方法), 这些值可以被改变,也可以被删除。这种方法允许这些额外的细节从默认值改变。默认情况下,使用Object.defineProperty()添加的属性值是不可变的 --MDN

Vue 2.xReact.js 16.x 还有Angular都是基于此来实现数据监听, AngularJS 用的脏检查

从介绍可以看出, 此函数可以用来创建一个属性, 或者监听已有的属性
没错, 它是作用于属性级别的, 也就是说, 如果你的属性值是一个复杂类型, 那就 GG 了
可以看下方的参考文章, 或者去 GITHUB 搜, 大部分是用的订阅者模式

Proxy

用于定义基本操作的自定义行为(如属性查找,赋值,枚举,函数调用等)。 -- MDN

从介绍得知, 这个面向的是整个变量
目前应该是支持 13 种代理操作, 常用的有 get , set, construct
如果变量的值是复杂类型, 需要再次监听, 简而言之就是: 递归监听复杂类型

var data = {}
var obj = loopObserver(data);

function observer(data) {
    return new Proxy(data, {
        get: function (target, key, receiver) {
          console.log(`getting`, key);
          return Reflect.get(target, key, receiver);
        },
        set: function (target, key, value, receiver) {
          console.log(`setting`, key, '->', value);
          value = loopObserver(value)
          return Reflect.set(target, key, value, receiver);
        }
    });
}

function loopObserver(data) {
    Object.keys(data).map(key => {
        if (typeof data[key] == 'object') {
            if (Object.keys(data[key]).length > 0) {
                data[key] = loopObserver(data[key]);
            } else {
                data[key] = observer(data[key])
            }
        }
        if (typeof data[key] == 'array') {
            data[key] = observer(data[key])
        }
    })
    if (typeof data =='object' || typeof data == 'array') {
        data = observer(data);
    }

    return data;
}

obj.info = {
    age: 22,
    heart: 110,
    walk: [234,,4523,23,523,5,235]
}

obj.info.age = 33;
obj.info.walk.push(999);
obj.info.walk[0] = 123;

参考

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Proxy
https://juejin.im/post/5acd0c8a6fb9a028da7cdfaf

本文链接:https://note.lilonghe.net/post/defineproperty-and-proxy.html

-- EOF --