對象最多見的用法是:建立,設置,查找,刪除,檢測和枚舉它的屬性。屬性包括名字和值。屬性名能夠是包含空字符串在內的任意字符串,屬性值能夠是任意JavaScript的值。除了名字和值意外,每一個屬性還有一些與之相關的值,稱爲:屬性特性,
(1) 可寫,代表是否能夠設置改屬性的值
(2) 可枚舉,代表是否能夠經過for/in循環返回該屬性
(3) 可配置,代表是否能夠三次或者修改該屬性
每一個對象還擁有三個相關的對象特性
(1) 對象的原型:指向另一個對象,本對象的屬性繼承自它的原型對象
(2) 對象的類:是一個標識對象類型的字符串
(3) 對象的擴展標記:指明瞭是否能夠向該對象添加新的屬性數組
(1) 對象直接量
var obj = {x:1,b:2}
(2) 經過new建立
var obj = new Array()
var date = new Date()
(3) 經過Object.create()建立
var obj = Object.create()
複製代碼
每個JavaScript對象(null除外)都和另外一個對象相關聯,‘另外一個’對象就是咱們熟知的原型,每個對象都從原型繼承屬性。用對象直接量建立的對象都具備同一個原型對象,經過Object.prototype得到對原型對象的引用。經過new建立的對象,原型就是構造函數的prototype屬性的值,好比:Array.prototype,Date.prototype。沒有原型對象的:Object.prototype就只其中之一。普通對象都具備原型,Array.prototype的屬性繼承自:Object.prototye, 所以:new Date()建立的Date對象的屬性同時繼承Date.prototype,和Object.prototye,這就是原型鏈bash
能夠經過點(.)或者方括號([]),好比:obj.a 或者 obj['a']均可以得到屬性值, ECMAScript 3中,點運算符後的標識符不能使用保留字,ES5放寬了限制,常見的兩種例外狀況:對象屬性名是個關鍵字,那麼只有用中括號去訪問,若是屬性名是個不肯定參數,那麼也只能用中括號去訪問函數
delete運算符只能刪除自由屬性,不能刪除繼承屬性,也不能刪除那些不可配置的屬性,返回值是true或者falseui
判斷某個屬性是否存在於某個對象中,能夠經過in運算符,hasOwnProperty() 和proertyIsEnumerable()方法
(1)in運算符 (檢測自有屬性和繼承屬性)this
var obj = { x: 1, y: 2}
"x" in obj
// 左側是屬性名,右側是對象,若是對象的自有屬性或繼承屬性含有這個屬性,返回true
複製代碼
(2)hasOwnProperty()函數(檢測自有屬性)spa
var obj = { x:1, y:2}
obj.hasOwnProperty('x')
// hasOwnProperty()用來檢測是不是對象的自有屬性,不會查找原型屬性的
複製代碼
(3)propertyIsEnumerable()是hasOwnProperty()的加強版,只有檢測到自有屬性且這個屬性的可枚舉性爲true的時候,才返回trueprototype
枚舉屬性: for-in 循環。
for-in循環能夠在循環體中遍歷對象中全部可枚舉的屬性,包括自有屬性和繼承屬性,把屬性名稱賦值給循環變量,切記:對象繼承的內置方法不可枚舉code
var obj = { x:1, y:2, z:3}; // 三個都是可枚舉的屬性
obj.propertyIsEnumerabel('toString') // =>false 不可枚舉
for(item in obj) {
console.log(item) // 輸出:x,y,z,沒有toString
}
// 切記: 對象繼承的內置方法是不可枚舉的
for(item in obj){
if(!obj.hasOwnProperty('item')
continue; // 跳過繼承的屬性
}
for(item in obj) {
if(typeof obj[item] === 'function') {
continue; // 跳過方法
}
}
複製代碼
除了for-in循環以外,還有兩個方法
(1)Object.keys(), 返回一個數組,這個數組有對象中可枚舉的自有屬性的名稱組成
(2)Object.getOwnPropertyNames() 返回數組,只是它返回對象的全部自有屬性的名稱,而不單單是可枚舉的屬性,還包括不可枚舉屬性對象
對象屬性是由名字,值,和一組特性構成。屬性值能夠用一個或者兩個方法替代,這兩個方法就是getter,和setter,簡稱「存取器屬性」。
數據屬性只有一個簡單的值。
和數據屬性同樣,存取器屬性也是能夠繼承的繼承
能夠認爲一個屬性包含:一個名字和4個特性。
var obj = { x:1, y:2, z:3};
console.log(Object.getOwnPropertyDescriptor(obj, 'x'))
// 返回: {value:1, writable:true, enumerable:true, configurable: true}
複製代碼
存取器屬性:{set: undefined,get:function,enumerable:true,configurable:true} Object.getOwnPropertyDescriptor()只能獲得自有屬性,
要想得到繼承屬性的特性,須要遍歷原型鏈:用Object.getPrototypeOf()
想要設置屬性特性,或者新建屬性具備什麼特性:用Object.definePeoperty()
var obj = {};
Object.defineProperty(obj, 'x',{
value: 'zlm',
writable: true, // 可編輯
enumerable: false, //不可枚舉
configurable: true
})
console.log(obj.x) // => zlm 屬性是存在的
console.log(Object.keys(obj)) // =>[] 不可枚舉,因此輸出空數組 []
Object.defineProperty(obj,'x', {
writable:false
})
obj.x = 222;
console.log(obj.x) // =>zlm,值沒有改變,由於是不可寫入
Object.defineProperty(obj, 'x',{
value: 444
})
console.log(obj.x) // =>444 屬性依然可配置,因此值能夠修改
Object.defineProperty(obj, 'x', {
get: function() {
return 555;
}
})
console.log(obj.x) // =>555 將x從數據屬性修改成存取器屬性
複製代碼
注意:Object.defineProperty()不能修改繼承屬性,同時要修改或建立多個屬性,使用:Object.defineProperties()
// 第一個參數是:要修改的對象
// 第二個參數是:一個映射表,包含新建或者修改的屬性名稱和屬性描述符
var p = Object.defineProperties({},{
x: {value:1,writable:true,enumerable:true,configurable:true},
y: {value:2,writable:true,enumerable:true,configurable:true},
z: {
get: function() { return this.x * this.x + this.y *this.y },
enumerable:true,
configurable: true
}
})
console.log(p.x , p.y , p.z)
複製代碼
屬性特性的複製
Object.defineProperty(Object.prototype, 'extentd', {
writable:true,
enumerable: false,
configurable:true,
value: function(o) {
//遍歷o對象中全部的自有屬性
var names = Object.getOwnPropertyNames(o)
for(var i =0; i< names.length; i++) {
if(names[i] in this) continue
// 獲取o中的屬性的描述符
var desc = Object.getOwnPropertyDescriptor(names[i])
// 給當前對象建立一樣的屬性描述符
Object.defineProperty(this,names[i],desc)
}
}
})
複製代碼
function classof(o) {
if(o === null) return "NULL";
if(p === undefined) return "Undefined";
return Object.prototype.toString.call(o).slice(8, -1)
}
classof({})
classof(null)
classof("")
classof(false)
classof([])
classof(new Date())
classof(/,/)
classof(window)
複製代碼
(3)對象的可擴展性表示是否能夠給對象添加新屬性,全部內置對象和自定義對象都是顯示可擴展的
ES5提供了能夠用來查詢和設置對象的可擴展性函數:Object.esExtensible()
設置對象爲不可擴展,封閉的:Object.preventExtensions(),Object.seal()
檢測對象是否封閉:Object.isSealed()
更嚴格的鎖定對象,凍結:Object.freeze()
檢測對象是否凍結:Object.isFrozen()
對象的序列化是指:將對象的狀態轉換爲字符串,也可將字符串還原爲對象 ES5提供了內置函數:JSON.stringify() 用來序列化,JSON.parse()還原對象