花了一個半小時寫的,請懷着一顆感恩的心閱讀,謝謝!
我在說明一個事物和概念時,喜歡先上代碼看到效果,然後再解釋概念。
ES5新增的函數Object.defineProperty(),可以給JavaScript對象增加屬性。啊……,那以前的json對象不是本來就可以嗎。爲何還得搞出個這麼複雜的函數來做這個事情。
一、代碼部分(先上代碼):
1、回顧一下json對象增加屬性
如果沒有問題,可以不看本段。
//定義一個對象
Var person = {};
//給對象增加一個屬性
Person.age = 12;
Person.name = “張三瘋”;
Person.isAdult =”未成年”;
Ok,沒有問題。但是:
1)、思考一個問題,age屬性的值應該是有個用有效範圍的(如:0-150),但是,這樣增加的屬性沒法限制age屬性的取值範圍
2)、如果age屬性的變化,會引起其它屬性的變化,即其它屬性的值會隨着age的變化而變化,這樣沒法很好控制,而且很容易控制不好。如以上屬性isAdult的值,不能直接隨便賦值,而是age的值變化後,isAdult 的值會跟着變化。
2、如何用 Object.defineProperty()函數給對象增加屬性。
Var person = {};
Object.defineProperty(person ,"name",{
value:"張三瘋",
writable:false//屬性name不能修改
});
Console.log(person.name);//張三瘋
person.name = "隔壁老王"; //修改不成功
console.log(person.name);//張三瘋
沒想到吧,我們還可以讓某些屬性的值是隻讀的。
3、如果用 Object.defineProperty()進行給對象增加屬性,該屬性的取值是可控的,而且會影響其它屬性的變化。
注意:以下代碼中,在對象的定義中,寫的是帶下劃線的:_age,而在defineProperty()函數裏寫的屬性名是不帶下劃線的:age,外部使用該對象的屬性時,用不帶下劃線的:
let person = {
_age:12,
isAdult:"未成年"
};
Object.defineProperty(person,"age",{
get:function(){
return this._age;
},
set:function(newValue){
//此判斷是限制屬性的取值範圍是0-150之間
if(newValue<0 || newValue>150){
return;
}
this._age = newValue;
//此判斷是 _age屬性的值影響isAdult的值。
if(this._age>=18){
this.isAdult = "已成年";
}else{
this.isAdult = "未成年";
}
}
});
person.age = 16; //此句話會調用 set函數。
console.log(person.age);//此句話對調動get函數
console.log(person.isAdult);//未成年
person.age = 25; //此句話會調用 set函數。
console.log(person.age);//此句話對調動get函數
console.log(person.isAdult);//已成年
二、概念:
1、普及一個概念,JavaScript的屬性有三種類型(重點看前兩點):
1)、命名數據屬性:擁有一個確定的值的屬性。這也是最常見的屬性。
2)、命名訪問器屬性:通過getter和setter進行讀取和賦值的屬性(這是今天重點要說的)
3)、內部屬性:由JavaScript引擎內部使用的屬性,不能通過JavaScript代碼直接訪問到,不過可以通過一些方法間接的讀取和設置。比如,每個對象都有一個內部屬性[[Prototype]],你不能直接訪問這個屬性,但可以通過Object.getPrototypeOf()方法間接的讀取到它的值。雖然內部屬性通常用一個雙呂括號包圍的名稱來表示,但實際上這並不是它們的名字,它們是一種抽象操作,是不可見的,根本沒有上面兩種屬性有的那種字符串類型的屬性
2、Object.defineProperty()的作用就是直接在一個對象上定義一個新屬性,或者修改一個已經存在的屬性。
3、Object.defineProperty()函數的格式:
Object.defineProperty(obj, prop, desc)
參數:
Obj:表示增加屬性的對象
Prop:屬性名
Desc:屬性描述符
4、屬性描述符
1)、概念:
屬性描述符,是對當前屬性的描述(包括設置)。
如 以上代碼:
Object.defineProperty(person ,"name",{
value:"張三瘋"
});
中的value就表示name屬性的值爲 “張三瘋”。
2)、屬性描述分爲:數據描述符和存取描述符,
(1)、數據描述符有兩個:value和writable
(2)、存取描述符:是由一對 getter、setter 函數功能來描述的屬性
3)、共有的描述符:
數據描述符和存取描述均具有以下描述符
Configrable,enumerable
4)、屬性描述符的解釋
Value: 屬性的取值
Writable:屬性是否可以修改
configurable描述屬性是否配置,以及可否刪除
enumerable 描述屬性是否會出現在for in 或者 Object.keys()的遍歷中
get:針對命名訪問器屬性值的獲取
Set:針對命名訪問器屬性值的修改
默認值:
屬性名 |
默認值 |
Value |
Undefined |
Writable |
False |
configurable |
False |
enumerable |
False |
get |
Undefined |
Set |
Undefined |