Object.defineProperty方法直接在一个对象上定义一个新属性,或者修改一个已经存在的属性,并返回这个对象。
Object.defineProperty(obj, prop, desc)方法接受三个参数:
obj: 当前对象
prop: 当前对象的属性名
desv:一个描述符对象,通过描述符的设置,可以更精准的控制对象属性
Object.defineProperty(person, "age", {
value: 27, // 属性值
enumberable: true, // 能否通过for in循环访问属性,默认true,
writable: true, // 能否被修改,默认true,
configurable: true, // 能否被删除,默认true
get: function() {
return this.value;
},
set: function(newValue) {
return newValue;
}
})
实践一下:
var person = {
age: 27,
type: "青少年"
}
Object.defineProperty(person, "age", {
get: function() {
return this.age;
},
set: function(newAge) {
if (newAge > 35) {
this.age = newAge;
this.type = "中年人";
}
}
})
person.age = 40;
console.log(person.type); // "中年人"
console.log(person.age); // 40
模拟Vue中v-module数据双向绑定原理:
<!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>
<style>
#myInput {
width: 400px;
height: 50px;
font-size: 40px;
color: rgb(29, 27, 27);
}
#showInput {
margin-top: 20px;
width: 400px;
height: 200px;
border: 1px solid rgb(250, 248, 114);
}
</style>
</head>
<body>
<input id="myInput" type="text" />
<div id="showInput"></div>
<script>
var text;
data = {};
var oIn = document.getElementById("myInput");
var oDiv = document.getElementById("showInput");
oIn.addEventListener("input", function (e) {
text = e.target.value;
console.log(text);
window.data.value = text;
});
Object.defineProperty(data, "value", {
get() {
return "我就是我";
},
set(v) {
oDiv.innerHTML = v;
},
});
data.value = 123;
console.log(data.value);
</script>
</body>
</html>
打印结果:
Vue响应原理的核心是数据劫持和依赖收集,主要是利用Object.defineProperty()
实现对数据存取操作的拦截,我们把这个实现称为数据代理;同时我们通过对数据get方法的拦截,可以获取到对数据的依赖,并将出所有的依赖收集到一个集合中。