Object defineProperty
- 一、簡介
- 1. 屬性表
- 2.互斥性
- 3. get、set的簡單使用
- 二、深入
- 1.定義常量
- 2. Object.preventExtensions() 禁止對象拓展(不可逆)
- 3. Object.seal() 密封(不可逆)
- 4. Object.freeze() 凍結(不可逆)
- 三、應用
一、簡介
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雙向綁定……