1. writable configurable enumerable
let obj = {
a: 1
}
Object.defineProperty(obj, 'b', {
value: 2,
//writable: false//不可修改
//configurable: false //控制descriptor内属性都不可改变
enumerable: false //是否可以枚举
})
obj.b = 5
console.log(Object.keys(obj))//["a"]
for (const key in obj) {
console.log(key)//a
}
console.log(obj,obj.b) //{a: 1, b: 2} 2
2. set和get这也是vue3.0前Observe的实现原理
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div></div>
<input type="text">
<button>修改为1234</button>
</body>
</html>
<script>
//类似 vue的data
let obj = {}
/*
*obj 要劫持的对象
*name 要劫持对象的属性
*callback 劫持以后的操作
*/
function watch(obj, name, callback) {
let value = obj.name
Object.defineProperty(obj, name, {
set(msg) {
// 触发setter给obj赋值
value = msg
//执行劫持后的操作
callback(value)
},
get() {
//返回获取属性值
return value
}
})
}
function doSomething(value) {
document.querySelector('div').innerHTML = value
document.querySelector('input').value = value
}
//监听input变化
//可以参考全兼容版:https://segmentfault.com/a/1190000017524278
document.querySelector('input').addEventListener('input', (e) => {
obj['msg'] = e.target.value
})
document.querySelector('button').addEventListener('click', () => {
obj['msg'] = 1234
})
watch(obj, 'msg', doSomething)
</script>
上面实现了一个简易版的双向绑定