说到vue实现响应式的实现原理,我们都知道是通过Object.defineProperty
,那么具体是怎么实现的呢?今天我们就来详细的探讨一下Object.defineProperty吧。
1.Object.defineProperty是什么?
官方解释:该方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性, 并返回这个对象。
顾名思义,就是为对象定义属性。
我们都知道,为对象定义属性或者修改属性,我们常用的有.
操作符或者[""]
操作符,.
操作符被称为“属性访问”,[""]
被称为“键访问”
我们如果要增加一个新属性或者修改一个已有的属性并且它的特性进行设置,就需要用到Object.defineProperty了。
语法
Object.defineProperty(obj, prop, descriptor)
参数
obj:要在其上定义属性的对象。
prop:要定义或修改的属性的名称。
descriptor:将被定义或修改的属性描述符。
属性描述符
- value:属性值,默认为undefined
- writable:是否可写,布尔值,如果设置成false,则对属性的改写是没有作用的。默认为false,不可写。而上面提到的无论是属性访问还是键访问,writable默认都是true。
var obj = {
a:1
}
Object.defineProperty(obj,"a",{
value:2,
writable:false
})
console.log(obj.a);//2
obj.a = 3;
console.log(obj.a);//2
- enumerable:是否可枚举,布尔值,判断是否能在for-in循环中遍历出来。默认为false,不可枚举
var obj={
a:1,
b:2
}
Object.defineProperty(obj,"a",{
value:2,
writable:false,
enumerable:false
})
for(var key in obj){
console.log(key)//b
}
- configurable:是否可配置,布尔值,默认false。如果configurable是false,如果我们去把它改成true,会报一个TypeError错误,所以把configurable修改成false是单向操作,无法撤销,不过这里要说的是即使configurable是false,我们还是可以把writable由true改为false。
js 常见的几种错误类型
var obj={
a:1,
}
Object.defineProperty(obj,"a",{
value:2,
writable:false,
enumerable:false,
configurable:false
})
Object.defineProperty(obj,"a",{
value:4,
writable:true,
enumerable:false,
configurable:true
})
console.log(obj.a);//Uncaught TypeError
var obj={
a:1,
}
Object.defineProperty(obj,"a",{
value:2,
writable:true,
enumerable:false,
configurable:true
})
console.log(obj.a);//2
obj.a = 3;
console.log(obj.a);//3
Object.defineProperty(obj,"a",{
value:4,
writable:false,
enumerable:false,
configurable:true
})
console.log(obj.a);//4
obj.a= 5;
console.log(obj.a);//4
另外,configurable变成false还会禁止删除这个属性delete
var obj={
a:1,
}
delete obj.a;
console.log(obj.a);//undefined
Object.defineProperty(obj,"a",{
value:2,
writable:true,
enumerable:false,
configurable:false
})
delete obj.a;
console.log(obj.a);//2
存取描述符:
- 【get】一个给属性提供 getter 的方法,默认undefined。当访问该属性时,就会执行该方法,并返回结果。执行时没有参数传入,但是会传入this对象。
- 【set】 一个给属性提供 setter 的方法,默认undefined。当属性值修改时,触发执行该方法。该方法将接受唯一参数,即该属性新的参数值。
注意:value、wriable和get,set不能混用,会报错
var o = {};
var num = 5;
Object.defineProperty(o,"a",{
get:function(){
console.log("获取值");
return num;
},
set:function(val){//val参数代表的是新设置的值
console.log("设置值");
num= val+1;
}
})
o.a = 10;
console.log(o.a);//11
o.a = 11;
console.log(o.a);//12
console.log(num);//12
image.png
实现双向绑定demo-MVVM
<body>
<h2>实现一个简单的双向绑定</h2>
<input type="text" id="inp">
<p id="Txt"></p>
<script type="text/javascript">
var inp = document.querySelector("#inp");
var Content = document.querySelector("#Txt");
var obj={};
Object.defineProperty(obj,"inVal",{
get:function(){
return this._defaultVal;
},
set:function(newVal){
this._defaultVal = newVal;
inp.value = newVal;
Content.innerText =newVal;
}
})
inp.onkeyup= function(){
obj.inVal = this.value;
}
setTimeout(() => {
obj.inVal ="";
}, 5000);
</script>
image.png
网友评论