<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<main>
<p>请输入:</p>
<input type="text" id="input">
<p id="p"></p>
</main>
</body>
<script>
const obj = {};
Object.defineProperty(obj, 'text', {
get: function() {
console.log('get val');
},
set: function(newVal) {
console.log('set val:' + newVal);
document.getElementById('input').value = newVal;
document.getElementById('p').innerHTML = newVal;
}
});
const input = document.getElementById('input');
input.addEventListener('keyup', function(e){
obj.text = e.target.value;
})
</script>
</html>
优点:
- 监听所有属性不需要遍历所有
- 可以监听数组的变化
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<main>
<p>请输入:</p>
<input type="text" id="input">
<p id="p"></p>
</main>
</body>
<script>
const input = document.getElementById('input');
const p = document.getElementById('p');
const obj = {};
const newObj = new Proxy(obj, {
get: function(target, key, receiver) {
console.log(`getting ${key}!`);
return Reflect.get(target, key, receiver);
},
set: function(target, key, value, receiver) {
console.log(target, key, value, receiver);
if (key === 'text') {
input.value = value;
p.innerHTML = value;
}
return Reflect.set(target, key, value, receiver);
},
});
input.addEventListener('keyup', function(e) {
newObj.text = e.target.value;
});
</script>
</html>
从Object.definedProperty到Proxy
- 无法监听利用索引直接设置数组的一个项,例如:
vm.items[indexOfItem] = newValue
- 无法监听数组的长度的修改,例如:vm.items.length = newLength
- 无法监听 ES6 的 Set、WeakSet、Map、WeakMap的变化
- 无法监听 Class 类型的数据;
- 无法监听对象属性的新加或者删除;
面试官: 实现双向绑定Proxy比defineproperty优劣如何? JavaScript 设计模式精讲 - 第三章 11代理模式