上文中提到JavaScript對象是屬性的集合,本結就來談談對象的屬性以及對屬性的操做。我的認爲,JavaScript中對象的屬性比其餘語言複雜不少,因爲本屌的主業是PHP,所以當初看書時候也花了不少時間才把這部份內容給理清了。javascript
跟傳統的面向對象不太同樣,JavaScript對象是動態的,便可以隨時對一個js對象新增或刪除屬性,對屬性最多見的操做是設置、查找、刪除、檢測、枚舉。除此之外,每一個屬性還有一些與之相關的值,稱爲「屬性特性」:java
正是因爲上述3中屬性特性使得JavaScript中屬性相對其餘語言來講複雜了不少。此外,根據屬性的定義位置,能夠把屬性分爲:數組
因爲對象的屬性一部分是由本身定義,還有一部分屬性是從原型對象那繼承下來,所以假如要查詢對象o中的屬性x時,若是o中不存在,js引擎將會陸續在o的原型對象中來尋找x,若是整條原型鏈中都找不到或者找到一個原型是null的對象,則返回undefined函數
var o = {}; o.x = 1; p = inherit(o); //建立一個新對象p,原型對象爲o,inherit函數請查看上一篇 console.log(p.x); //返回1,因爲在對象p中找不到屬性x,則js引擎在它的原型對象中繼續查找
如今假設給給對象o的屬性x賦值,若是o中以及有自有屬性x,則賦值操做值就直接改變該屬性的值,若是不存在,則賦值操做給o新增這個屬性x。若是o中的原型鏈中也有該屬性,則繼承的屬性就被這個新建立的屬性覆蓋了。this
上述對屬性的賦值是基於一種理想狀況,事情每每不會那麼簡單,上面以及提到,每個屬性都有3個屬性特性:可寫、可枚舉、可設置,若是對象o中繼承了一個只讀屬性的x,則賦值操做是不被容許的。spa
在JavaScript中,只有在查詢屬性時,才能體會到繼承的存在。code
刪除一個JavaScript對象的屬性可使用delete運算符,然而須要注意的是:delete只是斷開屬性和宿主對象的聯繫,而不會去操做屬性中的屬性,在銷燬一個對象時應特別注意這點;此外delete只能刪除自有屬性,不能刪除繼承屬性,所以若是要刪除繼承屬性,須要先找到原型鏈中的該擁有該屬性的對象才能刪除它。對象
若是碰到那種可配置性爲false的屬性,如經過變量聲明或函數聲明建立的全局的對象,是不能被刪除的,在嚴格模式下,刪除一個不可配置的屬性會報一個類型錯誤。blog
檢測一個屬性是否屬於某個對象有如下幾種方法:繼承
var o ={}; o.x = 1; p = inherit(o); p.y = 2; o.hasOwnProperty("x"); //返回true p.hasOwnProperty("x"); //返回false Object.property.propertyIsEnumerable("toString"); //返回false,toString()方法不可枚舉
經過for/in循環能夠遍歷出對象中全部可枚舉的屬性(包括自有屬性和繼承屬性),通常來講,對象的內置方法是不可枚舉的,但在代碼中定義的屬性一般都是能夠枚舉,除非顯式地指定該屬性爲不可枚舉,例如:
var o ={x:1 , y:2, z:3}; o.propertyIsEnumerable("toString"); //返回false for(p in o){ console.log(p); } //循環輸出1,2,3,但不會輸出toString.
在ECMAScript5中定義了兩個用於枚舉屬性名稱的函數Object.keys()和Object.getOwnPropertyNames(),前者返回一個由對象中可枚舉且自有屬性組成的數組,後者也返回一個數組,可是它返回的是自有屬性的名稱,無論其是否可枚舉,在ECMAScript3中能夠用如下方法來模擬前者:
1 function keys(o){ 2 if(typeof o !== "object") throw TypeError(); 3 var result = []; 4 for(prop in o){ 5 if (!o.hasOwnProperty(prop)) continue; 6 else result.push(prop); 7 } 8 return result; 9 }
在ECMAScript5中,屬性值能夠用一個或兩個方法替代,這兩個方法就是getter和setter,由這兩個方法定義的屬性稱做「存取器屬性」,不一樣於「數據」屬性,它不具備寫屬性。
若是一個存取器屬性同時具備getter和setter方法,則這個屬性是可讀寫的,若是隻有getter那麼它就是個只讀屬性;若是隻有setter方法,則是一個只寫屬性,讀取它時返回undefined
var o ={ x : 2, y : 3, get z(){ return this.x*this.y; }, set z(value){ this.x += value; this.y += value; } }; console.log(o.z); //返回6 o.z = 2; console.log(o.z); //返回20