defineProperty和proxy的区别

defineProperty和proxy的区别

响应式的目的

当对象属性被读取后,被修改后,我要介入进行一些操作。
属性值的读和修改变成函数

defineProperty

他是针对属性的监听,所以对obj下的每个属性(深度遍历)进行监听。
天生缺陷:深度遍历效率缺失;由于遍历,新增属性他是没有被监听的;

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
30
31
const obj = {
a:1,
b:2,
c:{
d:3,
e:4
},
}
function _isObject(v){
return typeof v==='object' && v != null
}
function observe(obj){
for(const k in obj){
let v = obj[k]
if (_isObject(v)){
observe(v)
}
Object.defineproperty(obj,'a',{
get(){
console.log('a','读取')
return v
},
set(newval){
if(v != newval){
v = newval
console.log('a','更改')
}
}
})
}
}

proxy监听整个对象

Proxy返回一个新的代理对象,不动原数据
监听的是整个对象,所以不需要遍历,新增时可以收到通知

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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
const obj = {
a:1,
b:2,
c:{
d:3,
e:4
},
}
function _isObject(v){
return typeof v==='object' && v != null
}

function observe(obj){
const proxy = new Proxy(obj,{
get(target,k){
let v = target[k]
if(_isObject(v)){ //这里是有递归,但只有v被读到才会触发。
observe(v)
}
console.log(k,'读取')
return v
},
set(target,k,val){
if(target[k] != val){
target[k] = val
}
}
})
return proxy
}

const proxy = new Proxy(obj,{
get(target,k){
let v = target[k]
console.log(k,'读取')
return v
},
set(target,k,val){
if(target[k] != val){
target[k] = val
}
}
})