关于javascript中defineProperty的学习
語法
Object.defineProperty(obj, prop, descriptor)
參數
obj要在其上定義屬性的對象。prop要定義或修改的屬性的名稱。descriptor將被定義或修改的屬性描述符。
返回值
被傳遞給函數的對象。
使用說明:
我們一般給一個對象創建一個新的屬性時,大部分采用的都是如下方式:
var obj = {};
obj.key = "Hello"
但是這種創建方式的屬性,其值可被修改,可被遍歷等等。 如果想創建隱藏屬性(使用for in 無法遍歷出來)
或者想創建一個只讀屬性(不可寫入),使用這種方式就不可取了。在ES6中,有一個叫做Symbol類型的東西
這個東西可以人為的定義它是否可寫,可枚舉,可重配置等等,而定義這個Symbol的方法則是Object對象的 defineProperty
這里可以將Symbol理解為帶特殊技能的屬性。 我們可以為一個對象,使用defineProperty方法來定義一個帶紅藍buff的屬性
先來說說屬性描述符,由名稱可知是用來描述一個屬性具有什么特點用的,屬性描述符分為兩類: 數據描述符和存取描述符
數據描述符表示一個具有值的屬性,該值可能只讀,可能可寫
存儲描述符表示一個具有對數據進行存取操作的屬性。
一個屬性只能為以上兩種類別中的一個,不能同時是兩者
下面是一些上面兩個描述符可選的鍵值:
configurable: 是否允許改變描述符,是否允許刪除屬性,默認false
enumerable: 是否允許被枚舉(for in), 默認false
writeable: 是否可寫,默認false
value: 設定數據描述符的value值,默認是undefine
get: 設定存儲描述符的getter方法,默認undefine
set: 設定存儲描述符的setter方法,默認undefine
注意: configurable enumerable 這兩個描述鍵值 是數據描述符 與 存儲描述符 共有的
writeable 和 value 是數據描述符獨有的, 而set 和 get方法是存儲描述符獨有的,另外
這些選項不一定是自身的屬性,也需要考慮繼承,為確保留有默認值,需要凍結之前的
Object.prototype,或者將__proto__屬性指向null
說了那么多概念性的東西,下面來實戰練習一下吧
任務一: 創建一個帶有只讀屬性的對象
var o = {};
Object.defineProperty(o, "myName", {
value: "孫悟空",
writeable: false //不允許寫,只讀的
});
document.write(o.myName); //孫悟空
//嘗試改變屬性
o.myName = "豬八戒"; //這里不會報錯,但是會拋出readonly
document.write(o.myName); //孫悟空
任務二: 創建一個帶有"隱藏"屬性的對象
var o = {};
Object.defineProperty(o, "myName", {
value: "孫悟空",
enumerable: false //不允許被枚舉出來
});
//通過普通方式創建其他屬性
o.myAge = 33;
o.myAddress = "China";
//枚舉對象所有變量
for(var i in o){
document.write(i +":"+ o[i] + "<br>");
}
//輸出結果:
//myAge: 33
//myAddress: China
//雖然無法遍歷出來,但是依然是可以訪問的
document.write(o.myName); //孫悟空
任務三:創建一個帶有存儲描述符的屬性對象
var p; //稍后使用存儲描述符對他進行讀寫操作
var o = {};
Object.defineProperty(o, "b", { //屬性名為b
get: function(){
return p; //取全局變量
},
set: function(value){
p = value; //寫全局變量
},
enumerable: true, //可遍歷
configurable: true //可修改
});
o.b = 38; //看起來像是直接賦值,其實是調用了set方法賦值
document.write(p); //38, 因為get方法讀寫的對象是全局變量
存儲描述符,給人感覺像是對 對象的屬性進行讀寫操作,但其實背后可能是對其他變量的讀寫
操作,因為可以人為的定義讀寫操作執行的函數 set/get ,所以我們就可以實現讀寫時實現自己
想要的功能,比如數據類型判斷等等,如果對存儲描述符還是不太理解,可以看看下面兩段代碼
實現一個自存檔的屬性
function Archiver() {
var temperature = null;
var archive = [];
Object.defineProperty(this, 'temperature', {
get: function() {
console.log('get!');
return temperature;
},
set: function(value) {
temperature = value;
archive.push({ val: temperature });
}
});
this.getArchive = function() { return archive; };
}
var arc = new Archiver();
arc.temperature; // 'get!'
arc.temperature = 11;
arc.temperature = 13;
arc.getArchive(); // [{ val: 11 }, { val: 13 }]
第二段
var pattern = {
get: function () {
return 'I alway return this string,whatever you have assigned';
},
set: function () {
this.myname = 'this is my name string';
}
};
function TestDefineSetAndGet() {
Object.defineProperty(this, 'myproperty', pattern);
}
var instance = new TestDefineSetAndGet();
instance.myproperty = 'test';
// 'I alway return this string,whatever you have assigned'
console.log(instance.myproperty);
// 'this is my name string'
console.log(instance.myname);
對于configurable的效果,大家可能還有疑問,可以閱讀下面這段代碼,自己動手試試
var o = {};
Object.defineProperty(o, "a", { get : function(){return 1;},
configurable : false } );
// throws a TypeError
Object.defineProperty(o, "a", {configurable : true});
// throws a TypeError
Object.defineProperty(o, "a", {enumerable : true});
// throws a TypeError (set was undefined previously)
Object.defineProperty(o, "a", {set : function(){}});
// throws a TypeError (even though the new get does exactly the same thing)
Object.defineProperty(o, "a", {get : function(){return 1;}});
// throws a TypeError
Object.defineProperty(o, "a", {value : 12});
console.log(o.a); // logs 1
delete o.a; // Nothing happens
console.log(o.a); // logs 1
總結
以上是生活随笔為你收集整理的关于javascript中defineProperty的学习的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: could not change pro
- 下一篇: function module COM_