Object defineProperty
一、简介
defineProperty可以详细的配置一个对象的属性的特性和值
赋值的两种方式:
var time = {}
// 第一种
time.kind1 = 1; // var test = {kind1:1}
// 第二种
Object.defineProperty(time,"kind2",{
value:2
})
// ================================分割线===================================
// 第一种等价于
Object.defineProperty(time,"kind1",{
value:1,
writable:true,
enumerable:true,
configurable:true,
// get:undefined,
// set:undefined
})
// 第二种等价于
Object.defineProperty(time,"kind2",{
value:2,
writable:false,
enumerable:false,
configurable:false,
// get:undefined,
// set:undefined
})
1. 属性表
值 | 说明 | defineProperty后的默认值 | =后的默认值 | 拥有get、set后的默认值 |
---|---|---|---|---|
value | 属性的默认值 | undefined | undefined | get的return值(不能配置) |
writable | value是否可被重写,作用于等于号赋值和defineProperty赋值。configurable为false时,被设为false后就不能在被设为true | false | true | true(不能配置) |
enumerable | 是否可枚举(被循环显示)。configurable为false时,就不能再被更改 | false(为false时谷歌控制台显示该属性为淡紫色) | true | false |
configurable | 属性的配置项 是否可再此被定义,或被delete。configurable为false时,就不能再被更改 | false | true | false |
get | 获取属性值时调用的方法 | undefined | undefined | - |
set | 设置属性值时调用的方法 | undefined | undefined | - |
*[配置项]: 除value的选项 |
2.互斥性
数据描述符:value、writable;存取描述符:get、set
value、writable 不能与get、set共存:
当设置了value,就不需要再从get获取值(该从value取值还是从get取值);当设置了writable为false时,set将没有意义(不允许再修改)
get、set不能与value、writable共存:
当设置了get、set,就不需要从value获取、更改值(有了自定义的存取值方法);当设置set时,writable必须为true(必须允许修改)
3. get、set的简单使用
var time = {
__date: new Date(),
__lastEditTime: "",
__lastReadTime: "",
__remark: "",
__copyright: " (GeniusXYT)",
__getNow: function () {
return new Date().toLocaleString();
}
};
Object.defineProperty(time, "createTime", {
get() {
return this.__date.toLocaleString();
},
set(val) {
console.warn(`the obj property(now) do not be set ${val}.`);
},
enumerable: true
});
// 同时定义多个属性
Object.defineProperties(time, {
lastReadTime: {
get() {
return this.__lastReadTime;
},
enumerable: true
},
lastEditTime: {
get() {
return this.__lastEditTime;
},
enumerable: true
},
remark: {
get() {
this.__lastReadTime = this.__getNow();
return this.__remark ? this.__remark + this.__copyright : "";
},
set(val) {
this.__lastEditTime = this.__getNow();
this.__remark = val;
},
enumerable: true,
configurable: true // 可重写 enumerable、configurable、get和set
}
});
// 将带有__命名的变量(默认代表私有变量)隐藏(不可枚举)
(function hidePrivateVarible(obj) {
for (let k of Object.keys(obj)) {
if (k.slice(0, 2) === "__")
Object.defineProperty(obj, k, { enumerable: false, configurable: false });
}
})(time);
二、深入
1.定义常量
定义后属性值不能被更改(同const)
var time={};
// 方法一
Object.defineProperty(time,"author",{
value:"GeniusXYT",
writable:false,
enumerable:true,
configurable:false
})
// 方法二
Object.defineProperty(time,"author2",{
enumerable:true,
configurable:false,
get:function (){return "GeniusXYT"},
set:function(val){console.error("the obj time do not set property 'author',value '"+val+"'.")}
})
time.author="new name"
console.log(time.author)
2. Object.preventExtensions() 禁止对象拓展(不可逆)
禁止一个对象添加新属性并且保留已有属性
这样对象就不会再有新属性
var time = {};
time.prop = "prop";
console.log(Object.isExtensible(time));
Object.preventExtensions(time);
time.newProperty = "new";
console.log(time); // newProperty undefined
console.log(Object.isExtensible(time));
3. Object.seal() 密封(不可逆)
在对象上调用object.preventExtensions(),并把所有现有属性标记为configurable:false
这样对象就不会再有新属性,无法再配置特性
var time = {};
Object.defineProperty(time,"prop",{
value:"prop(i can configurable)",
writable:true,
enumerable:true,
configurable:true,
});
console.log(Object.isExtensible(time));
Object.seal(time);
time.newProperty = "new";
console.log(time); // newProperty undefined
console.log(Object.isExtensible(time));
Object.defineProperty(time,"prop",{writable:false}); // configurable为false时,可以将writable设为false;
time.prop = "new prop";
console.log(time.prop);
Object.defineProperty(time,"prop",{writable:true}); // 报错 设为false后将不能再设为true
Object.defineProperty(time,"prop",{enumerable:false}); // 报错 此时configurable已经被seal设置为false
Object.defineProperty(time,"prop",{configurable:true}); // 报错 configurable为false时,就不能再被更改
4. Object.freeze() 冻结(不可逆)
在一个对象上调用Object.seal(),并把所有现有属性标记为writable: false
这样对象就不会再有新属性,无法再配置特性,无法再设置值,对象就永远是那个对象了
var time = {};
Object.defineProperty(time,"prop",{
value:"prop(i can configurable)",
writable:true,
enumerable:true,
configurable:true,
});
console.log(Object.isExtensible(time));
Object.freeze(time);
time.newProperty = "new";
console.log(time); // newProperty undefined
console.log(Object.isExtensible(time));
Object.defineProperty(time,"prop",{writable:true}); // 报错 设为false后将不能再设为true
Object.defineProperty(time,"prop",{enumerable:false}); // 报错 此时configurable已经被seal设置为false
Object.defineProperty(time,"prop",{configurable:true}); // 报错 configurable为false时,就不能再被更改
time.prop = "new prop"; // 无效 此时的writable: false
console.log(time.prop);
三、应用
vue双向绑定……