我报名参加金石计划1期挑战——瓜分10万奖池,这是我的第1篇文章,点击查看活动详情
最近在研究了一下vue的双向绑定原理,顺便做了一下笔记。vue的核心就是通过Object.defineProperty()方法设置set和get函数来实现数据的劫持,在数据变化时发布消息给订阅者,触发相应的监听回调。也就是说数据和视图同步,数据发生变化,视图跟着变化,视图变化,数据也随之发生改变;那么Object.defineProperty()到底是怎么实现的,接下来详细的说一下。
首先Object.defineProperty()需要三个参数(object , propName , descriptor)
1、object 对象 => 给谁加
2、propName 属性名 => 要加的属性的名字 【类型:String】
3、descriptor 属性描述 => 加的这个属性有什么样的特性【类型:Object】
- configurable:表示能否通过delete删除属性从而重新定义属性,能否修改属性的特性,或者能否把属性修改为访问器属性,默认值为true。
- enumerable:表示能否通过for in循环访问属性,默认值为true
- writable:表示能否修改属性的值。默认值为true。
- value:包含这个属性的数据值。默认值为undefined。
接下来举几个例子来说明每个属性的使用
1、configurable:表示能否通过delete删除属性从而重新定义属性,能否修改属性的特性,或者能否把属性修改为访问器属性,默认值为true
// 可以删除star
let obj = {
name: "vue",
star: "5"
}
Object.defineProperty(obj, "star", {
configurable: true
})
delete obj.star;
console.log(obj.star); // undefined
// 不可以删除star
let obj = {
name: "vue",
star: "5"
}
Object.defineProperty(obj, "star", {
configurable: false
})
delete obj.star;
console.log(obj.star); // 5
2、enumerable:表示能否通过for in循环访问属性,默认值为true
// 可以枚举
let obj = {
name: "vue",
star: "5"
}
Object.defineProperty(obj, "star", {
enumerable: true
})
for(var i in obj){
console.log(i, obj[i]);
}
// name vue
// star 5
// 不可以枚举
let obj = {
name: "vue",
star: "5"
}
Object.defineProperty(obj, "star", {
enumerable: false
})
for(var i in obj){
console.log(i, obj[i]);
}
// name vue
3、writable:表示能否修改属性的值。默认值为true
// 可以修改
let obj = {
name: "vue",
star: "5"
}
Object.defineProperty(obj, "star", {
writable: true
})
obj.star = 6;
console.log(obj.star); // 6
// 不可以修改
let obj = {
name: "vue",
star: "5"
}
Object.defineProperty(obj, "star", {
writable: false
})
obj.star = 6;
console.log(obj.star); // 5
接下来重点来了,Object.defineProperty是怎么通过get、set来实现数据劫持的,看例子
get是获取值的时候的方法,类型为function,获取值的时候会被调用,不设置时为undefined
set是设置值的时候的方法,类型为function,设置值的时候会被调用,undefined
let visits = 10;
let obj = {
name: "vue",
star: "5",
};
Object.defineProperty(obj, "visits", {
get: () =>{
console.log("数据被获取了");
return visits;
},
set: (newValue)=> {
console.log("数据被设置了", newValue);
visits = newValue;
},
});
// 执行get,输出数据被获取了,然后打印出10
console.log(obj.visits);
// 执行set,数据被设置了 20, 再执行get,输出数据被获取了,然后打印出20
obj.visits = 20;
console.log(obj.visits);