defineProperty

2021/07/06

Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性, 并返回这个对象。

Object.defineProperty(obj, prop, descriptor)

obj:要在其上定义属性的对象。 prop:要定义或修改的属性的名称。 descriptor:将被定义或修改的属性描述符。 描述符可以有以下属性:

@return:传递给函数的对象。

example

// 数组拦截
/**
 *
 * @param {array} data
 */
function observe(data) {
    if (!Array.isArray(data)) {
        return;
    }
    // 取出所有数组遍历
    data.forEach(function(val,index) {
        Object.defineProperty(data, index, {
            enumerable: true, // 可枚举
            configurable: false, // 不能再define
            get: function() {
                return val;
            },
            set: function(newVal) {
                console.log('哈哈哈,监听到值变化了 ', val, ' --> ', newVal);
                val = newVal;
            }
        });
 });
};

// 对象拦截
/**
 *
 * @param {object} data
 */
function observe(data) {
    if (!data || typeof data !== 'object') {
        return;
    }
    // 取出所有属性遍历
    Object.keys(data).forEach(function(key) {
        let val = data[key]
        Object.defineProperty(data, key, {
            enumerable: true, // 可枚举
            configurable: false, // 不能再define
            get: function() {
                return val;
            },
            set: function(newVal) {
                console.log('哈哈哈,监听到值变化了 ', val, ' --> ', newVal);
                val = newVal;
            }
        });
 });
};

// Proxy监视对象包括数组变化
//必须针对`Proxy实例`(上例是proxy对象)进行操作才能触发
function observe(data) {
    if (!data || typeof data !== 'object') {
        return;
    }
    return new Proxy(data, {
        set(target, key, value, receiver) {
            console.log('哈哈哈,监听到值变化了 ', receiver[key], ' --> ', value);
            return Reflect.set(target, key, value, receiver);
        },
        get(target, name, value, receiver) {
            return Reflect.get(target, name, value, receiver);
        }
    })
}