JS 监听数据变化 defineProperty

Object.defineProperty,它可以监听数据变化,Vue2 内部就是利用 Object.defineProperty() 来实现对数据的监听和响应的。

注:这个是专门给 Object 使用的,其它类型不生效

监听属性变化通过定义 set 方法可以监听属性值改变示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
let model = {
message: 'hello'
};

let view = {};
Object.defineProperty(view, 'message', {
get: function() {
return model.message;
},
set: function(msg) {
console.log('监听到数据发生了变化')
model.message = msg;
}
});

view.message = 'world';
console.log(model.message); // 'world'

其它一些监听值示例:
监听 Object 对象的多个值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
let vm = {
name: "tom"
}
// vm 里边的 name 实际上可以进行监听
Object.keys(vm).forEach(key => {
definedAttribute(vm, key, vm[key])
})

function definedAttribute(vm, key, val){
Object.defineProperty(vm, key, {
enumerable: true,
configurable: false,
get(){
return val
},
set(newVal){
console.log("我监听到了数据的变化")
if(val !== newVal){
val = newVal
}
}
})
}

// 更新 vm 里面的数据
vm.name = "jerry"

// 输出:
我监听到了数据的变化 // 成功进行了监听

js监听一个变量的变化_wengqt的博客-CSDN博客_js监听

其它使用场景:

  1. 定义对象的只读属性可以通过设置 writable 为 false 和不定义 setter 来创建一个只读属性:

    1
    2
    3
    4
    5
    6
    7
    const obj = {};
    Object.defineProperty(obj, 'readOnlyProp', {
    value: 123,
    writable: false
    });

    obj.readOnlyProp = 456; // 无效,readOnlyProp仍为123
  2. 私有属性可以在构造函数中定义私有属性,这些属性只能在构造函数内部访问:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    function Person() {
    let privateProp = 'private';

    Object.defineProperty(this, 'publicProp', {
    get: function() {
    return privateProp;
    }
    });
    }

    let p = new Person();
    console.log(p.publicProp); // 'private'
    console.log(p.privateProp); // undefined
  3. 数据绑定可以通过 getter 和 setter 实现数据的绑定:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    let model = {
    message: 'hello'
    };

    let view = {};
    Object.defineProperty(view, 'message', {
    get: function() {
    return model.message;
    },
    set: function(msg) {
    model.message = msg;
    }
    });

    view.message = 'world';
    console.log(model.message); // 'world'

以上是 Object.defineProperty() 的一些常见使用场景,它提供了更精细地控制对象属性的能力。