这个东东其实没那么难,先来看看它的功能和使用方式:
Object.defineProperty(obj, prop, descriptor)
-
obj: 需要定义属性的对象。
-
prop: 需定义或修改的属性的名字。
-
descriptor: 将被定义或修改的属性的描述符。
-
返回值:返回传入函数的对象,即第一个参数obj。
三个参数都是必填的
关于描述符 descriptor
对象里目前存在的属性描述符有两种主要形式:数据描述符和存取描述符。数据描述符是一个拥有可写或不可写值的属性。存取描述符是由一对 getter-setter 函数功能来描述的属性。描述符必须是两种形式之一;不能同时是两者。
数据描述符和存取描述符均具有以下可选键值:
-
configurable
当且仅当该属性的 configurable 为 true 时,该属性描述符才能够被改变,也能够被删除。默认为 false。 -
enumerable
当且仅当该属性的 enumerable 为 true 时,该属性才能够出现在对象的枚举属性中。默认为 false。
数据描述符同时具有以下可选键值:
-
value
该属性对应的值。可以是任何有效的 JavaScript 值(数值,对象,函数等)。默认为 undefined。 -
writable
当且仅当该属性的 writable 为 true 时,该属性才能被赋值运算符改变。默认为 false。
存取描述符同时具有以下可选键值:
-
get
一个给属性提供 getter 的方法,如果没有 getter 则为 undefined。该方法返回值被用作属性值。默认为 undefined。 -
set
一个给属性提供 setter 的方法,如果没有 setter 则为 undefined。该方法将接受唯一参数,并将该参数的新值分配给该属性。默认为 undefined。
具体示例:
var o = {};
// o.mm = 'lyt'
Object.defineProperty(o, 'mm', {
value: 'lyt',
configurable: true,
enumerable: true,
writable: true
});
// 这种写法和上面的是一个意思。
如果configurable为默认值false,那么再去修改除writeable以外的属性都会抛出异常,也就是说这个属性是个总开关。
var o = {};
Object.defineProperty(o, 'mm', {
value: 'lyt'
});
Object.defineProperty(o, 'mm', { // 报错
configurable: true
});
如果enumerable为默认值false,则该属性不能被for-in循环所遍历。
var o = {};
Object.defineProperty(o, 'mm', {
value: 'Tina',
enumerable: true
});
Object.defineProperty(o, 'name', {
value: 'lyt'
});
for(var key in o){
console.log(o[key]); // Tina
}
如果writable为默认值false,那么属性将不可写,只能读。
var o = {};
Object.defineProperty(o, 'mm', {
value: 'Tina'
});
o.mm = 'lmm';
console.log(o.mm) // Tina
关于 get 和 set 函数
通过Object.defineProperty()来设置存储描述符的时候,当对对应的数据进行读取操作的时候会触发get函数,对数据进行写入操作的时候会触发set函数,下面这个例子就会让你搞清楚它们的作用:
var o = {};
Object.defineProperty(o, 'mm', {
get:function (){
console.log('卢雨婷大美妞取了我的值');
return 'Tina' // 返回值即使读取的值
},
set:function (value){ // 这个参数的名字随便
console.log(`我的值被卢小妞设置成了${value}`);
// 这里使用this.mm = value赋值要注意,会形成递归。
}
});
o.mm;
o.mm = '白痴';
至于取值和赋值的时候的行为,就随需求而定了。
应用:MVVM框架的基本原理
<div>
<p>你好: <span id="name">111</span></p>
<div id="intname">222</div>
</div>
<script>
var userInfo = {}; // 模拟后台数据
// 当对数据取值和赋值的时候对DOM进行相应的更新
Object.defineProperty(userInfo,'name', {
get:function () {
return document.getElementById('name').innerHTML;
},
set:function (value) {
document.getElementById('name').innerHTML = value;
}
})
Object.defineProperty(userInfo,'intname', {
get:function () {
return document.getElementById('intname').innerHTML;
},
set:function (value) {
document.getElementById('intname').innerHTML = value;
}
})
console.log(userInfo.name);
userInfo.name = 'lyt';
userInfo.intname = 'Tina';
console.log(userInfo.name);
</script>
总结:以上,你没看错,就这么简单。