MDN上是这样解释的:Object.defineProperty( )方法直接在一个对象上定义新的属性或修改现有属性,并返回该对象。
本文快速的讲解Object.defineProperty( ),在很多双向数据绑定的框架,都是基于这个方法去监听数据的变化的,所以这个Object的方法很重要.所以才用一篇文还在那个来讲解这个方法
本人Object.defineProperty( )对理解
当我们修改(删除,)一个对象(属性)时,Object.defineProperty( )可以可以拦截你的操作,监听数据的改变.
先看代码
<script>
var obj = {};//对象
Object.defineProperty(obj,'name',{
value:'chenm'
});
console.log(obj.name); //chenm
</script>
语法 Object.defineProperty(obj, prop, descriptor)
obj : 要修改操作的对象
prop: 要定义或修改的属性的名称。
descriptor: 将被定义或修改的属性描述符。
obj和prop这两个没有啥说的 那个我直接开始本方法的关键
descriptor属性描述符
MDN这样说: 对象里目前存在的属性描述符有两种主要形式:数据描述符和存取描述符。数据描述符是一个具有值的属性,该值可能是可写的,也可能不是可写的。存取描述符是由getter-setter函数对描述的属性。描述符必须是这两种形式之一;不能同时是两者。
说的太啰嗦,我都不想读,我给大家画个图(一下你就明白了)
注意 数据描述符的 (writable value) 和 存取描述(get,set) 只能够存在一种
<script>
var obj = {};
Object.defineProperty(obj, "key", {
enumerable: false,
configurable: false,
writable: false,
value: "static",
get: function () {
},
set: function (newValue) {
},
});
//会报错
// throws a TypeError: value appears only in data descriptors, get appears only in accessor descriptors
</script>
value:定义该属性的值,默认为 undefined。
<script>
var obj = {};
Object.defineProperty(obj, "key", {
value: 123456
});
console.log(obj.key)//输出//456
</script>
configurable:为 true 时,该属性描述符才能够再次被改变,同时该属性也能从对应的对象上被删除。默认为 false。
<script>
var obj = {};
Object.defineProperty(obj, "key", {
value: 123456,
configurable: false
});
delete obj.key;
console.log(obj.key); //123456
//configurable: false时删除无效,所以打印还是123456
</script>
configurable: true
<script>
var obj = {};
Object.defineProperty(obj, "key", {
value: 123456,
configurable: true
});
delete obj.key;
console.log(obj.key); //undefined
//configurable: true 时删除成功,所以打印还是undefined
</script>
enumerable:为true时,该属性才能够出现在对象的枚举属性中。默认为 false。
这里说一下枚举,是可以被 for…in 循环和 Object.keys() 查找出来
** 一下引用自掘金:化身孤岛的鲸…写的很不错直接借鉴一下) **
<script>
//1.enumerable为false
var obj = {age:25};
Object.defineProperty(obj,'name',{
enumerable:false,
value:'chenm'
});
for(let key in obj){
console.log(key) //age
}
console.log(Object.keys(obj))//["age"]
//Object.keys:返回该对象可枚举属性组成的数组。 enumerable为false时,name并不能枚举。
//注意当操作对象现有属性的时候 enumerable默认为true
//2.enumerable为true
var obj = {age:25};
Object.defineProperty(obj,'name',{
enumerable:true,
value:'chenm'
});
for(let key in obj){
console.log(key) //age name
}
console.log(Object.keys(obj)) //["age","name"]
</script>
writable:为true时,属性的值才能被 ‘=’ 赋值运算符赋值。默认为 false。
<script>
//1.writable为false
var obj = {};
Object.defineProperty(obj,'sex',{
writable:false,
value:'boy'
});
console.log(obj.sex); //boy
obj.sex = 'girl';
console.log(obj.sex); //boy
//writable 为false(默认就为false),sex是不能用'='赋值的。
//2.writable为true
var obj = {};
Object.defineProperty(obj,'sex',{
writable:true,
value:'boy'
});
console.log(obj.sex) //boy
obj.sex = 'girl'
console.log(obj.sex) //girl
</script>
get: 一个给属性提供 getter 的方法。当访问(获取)该属性时,该方法会被执行。
set: 一个给属性提供 setter 的方法。当修改该属性值时,该方法会被执行。
<script>
var obj = {};
let val = '15k';
Object.defineProperty(obj,'wages',{
get:function(){
//这是里获取属性的时候执行
console.log('我获取到你的值了。。。')
return val;
},
set:function(newVal){
//这是里修改属性值的时候执行
console.log('我修改了你的值。。。')
val = newVal
}
});
console.log(obj.wages);
obj.wages = '20k'
console.log(obj.wages);
//我获取到你的值了。。。
//15k
//我修改了你的值。。。
//我获取到你的值了。。。
//20k
</script>
<script>
//get,set一起出现,如果省略get,获取到的值都是undefined
var obj = {};
let val = '15k';
Object.defineProperty(obj,'wages',{
set:function(newVal){
//这是里修改属性值的时候执行
console.log('我修改了你的值。。。')
val = newVal
}
});
console.log(obj.wages) //undefined
obj.wages = '20k'
console.log(obj.wages)//undefined
//如果省略set, 无法赋值。
var obj = {};
let val = '15k';
Object.defineProperty(obj,'wages',{
get:function(){
//这是里获取属性的时候执行
console.log('我获取到你的值了。。。')
return val;
},
});
console.log(obj.wages) //15k
obj.wages = '20k'
console.log(obj.wages)//15k
</script>
根据Object.defineProperty()的get,set写一个简单的数据双向绑定。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<input type="text" id="input"/>
<span id="text"></span>
<button id="btn1">获取值</button>
<button id="btn2">修改值</button>
<script>
var obj = {
value:123
};
//初始化赋值
document.getElementById('input').value = obj.value;
document.getElementById('text').innerHTML = obj.value;
//监听input方法
document.getElementById('input').oninput = function(e){
obj.value = e.target.value;
};
//使用Object.defineProperty设置属性的get,set方法。
let val = obj.value;
Object.defineProperty(obj,'value',{
get:function(){
return val
},
set:function (newVal){
//当值被修改的时候 修改input&span的值
document.getElementById('input').value = newVal;
document.getElementById('text').innerHTML = newVal;
val = newVal;
}
});
document.getElementById('btn1').onclick = function (){
console.log(obj)
}
document.getElementById('btn2').onclick = function (){
obj.value = '修改了';
}
</script>
</body>
</html>
到此结束~~~~~~~~~~~~~~~~~~~~~~