對象其實能夠看作有許多鍵值對組合成的一個無序集合,能夠經過鍵倆訪問值。值通常由,基本數據類型 和 object 組合。javascript
有三種方式:java
使用new來建立一個對象
var person = new Object();
甚至能夠簡寫成爲: var person = new Object;
json
var o = { a : 1}; var p = new Object(o); alert(o === p); // true
var o1 = new Object("123"); console.log(o1); // String{0:"1",1:"2",2:"3",length:3,__proto__: String, [[PrimitiveValue]]: "123"} var o2 = new Object(123); console.log(o2) // Number{123, __proto__: Number, [[PrimitiveValue]]: 123} var o3 = new Object(true); console.log(o3) // Boolean {__proto__: Boolean, [[PrimitiveValue]]: true} // ------------ 下面是空對象 和不傳參數同樣。 var o4 = new Object(null) console.log(o4) // Object{__proto__: Object} var o5 = new Object(undefined) console.log(o5) // Object{__proto__: Object} var o6 = new Object() console.log(o6) // Object{__proto__: Object}
這是咱們 最熟悉的一種,也是常用的一種,其實使用字面量只是隱藏了與使用new操做符相同的基本過程,因而也能夠叫作語法糖。
簡單示例:數組
var person = { age : 24, name: 'xiaoming', 1: true, }
注意,使用對象字面量方法來定義對象的時候,屬性名會自動轉化爲字符串。
就是上面示例,自動變成下面的。函數
var person = { 'age' : 24, 'name': 'xiaoming', '1': true, }
ES5定義了一個名爲Object.create()的方法,它建立一個新對象,第一個參數就是這個對象的原型,第二個可選參數用以對對象的屬性進行進一步描述this
var o = Object({a:1}) console.log(o) // Object{a:1,__proto__:object}
注意:傳入參數null來建立一個沒有原型的新對象prototype
var o1 = Object.create(null); var o2 = {};
此時o1不會繼承任何東西,甚至不包括基礎方法。好比toString()和valueOf()。
若是想要建立一個普通的空對象(例如,經過{}或new Object()建立的對象),須要傳入Object.prototype, 這就是由於,這個函數的第一個參數就是原型對象。code
var o3 = Object.create(Object.prototype); var o4 = {};
若是不一樣的變量名指向同一個對象,那麼它們都是這個對象的引用,也就是說指向同一個內存地址。修改其中一個變量,會影響到其餘全部變量。對象
var o = { a:1, } var p = o; console.log(p.a) // 1 p.a = 0; console.log(o.a) // 0
對象的屬相操做,有兩種 [] 和 點號(.)。
點號(.), 在使用的時候,屬性名必須符合標識符的命名規則。
不存在的屬性取值返回undefined。繼承
var o = { a : 0, 1 : true, } o.b = 1; // 能夠增長屬性,並賦值 console.log(o.a) // 能夠取值操做 console.log(o.1) // 報錯 console.log(o.b) // undefined 不存在的變量 o.a = 2; // 能夠賦值操做 console.log(o.a);
[] 方括號中的值, 如果字符串,則直接訪問。 若是非字符串類型且不符合標識符命名,則轉成字符串訪問,若是非字符串類型且符合標識符命名,則須要識別變量的值,變量未定義,則報錯。
在[] 訪問屬性的時候 是能夠計算屬性的
var c = 1; var o = {} console.log(o[0]) // undefined o[0] --> o['0'] 訪問。 console.log(o[a]) // 報錯,a符合變量的命名規則,a未被定義,而報錯 console.log(o['a']) // undefined o['a'] 訪問。 console.log(o[null]) // undefined , o[null] --> o['null']訪問 console.log(o[c + 1]) // undefined o[c+1] --> o['4']訪問
注意 null和undefined不是對象,給它們設置屬性會報錯
使用delete運算符能夠刪除對象屬性(包括數組元素)。
delete是有返回值的,刪除成功則返回true,刪除不存在的屬性或非左值時,返回false。當使用delete操做符刪除不可配置的屬性時,返回false,嚴格模式下會拋出TypeError錯誤
將屬性賦值爲 null 和undefined 只是修改了屬性的值。
var o = { a:1 } console.log(delete o.a);//true console.log(o.a);//undefined console.log('a' in o);//false in 操做符 能夠判斷對象是否具備該屬性,可是沒法判斷是不是繼承來的
使用delete刪除數組元素時,不會改變數組長度
var a = [1,2,3]; delete a[2]; 2 in a;//false a.length;//3
每個javascript對象都和另外一個對象相關聯。「另外一個對象」就是咱們熟知的原型對象,每個對象都會從原型對象繼承屬性。
對象自己具備的屬性叫自有屬性,從原型對象繼承而來的屬性叫繼承屬性
in: in操做符能夠判斷對象是否可使用某一屬性,但沒法區別自有仍是繼承屬性
for-in: for-in循環能夠遍歷出該對象中全部可枚舉屬性
hasOwnProperty(): 能夠肯定該屬性是自有屬性仍是繼承屬性
Object.keys(): 返回全部可枚舉的自有屬性
Object.getOwnPropertyNames(): Object.keys()方法不一樣,Object.getOwnPropertyNames()方法返回全部自有屬性(包括不可枚舉的屬性)
對象屬性描述符分爲, 數據屬性 訪問器屬性
數據屬性(data property)包含一個數據值的位置,在這個位置能夠讀取和寫入值。
var o = {a:1}; Object.defineProperty(o,'a',{ configurable:false, }); delete o.a; //false 嚴格模式下報錯 console.log(o.a);//1
var o = {a:1}; Object.defineProperty(o,'a',{ configurable:false }); // 報錯不能修改屬性 Object.defineProperty(o,'a',{ configurable:true });
可枚舉enumerable
可枚舉性決定屬性是否出如今對象的屬性枚舉中,具體來講,for-in循環、Object.keys方法、JSON.stringify方法是否會取到該屬性。
var o = {a:1}; Object.defineProperty(o,'a',{enumerable:false}); for(var i in o){ console.log(o[i]);//undefined }
var o = {a:1}; Object.defineProperty(o,'a',{ writable:false }); console.log(o.a);//1 o.a = 2;//因爲設置writable爲false,因此o.a=2這個語句會默認失效,嚴格模式會報錯 console.log(o.a);//1
屬性值value
屬性值包含這個屬性的數據值,讀取屬性值的時候,從這個位置讀;寫入屬性值的時候,把新值保存在這個位置。默認值爲undefined
訪問器屬性不包含數據值;它們包含一對兒getter和setter函數(不過,這兩個函數都不是必需的)。在讀取訪問器屬性時,會調用 getter函數,這個函數負責返回有效的值;在寫入訪問器屬性時,會調用setter函數並傳入新值,這個函數負責決定如何處理數據。
get是一個隱藏函數,在獲取屬性值時調用。set也是一個隱藏函數,在設置屬性值時調用,它們的默認值都是undefined。Object.definedProperty()中的get和set對應於對象字面量中get和set方法
[注意]getter和setter取代了數據屬性中的value和writable屬性
一般這裏的get和set是用來 攔截數據訪問和修改的。
var o = { get a(){ return 0; } } console.log(o.a) // 0 o.a = 1 // 沒有set方法, 默認失效 console.log(o.a) // 0 // --------------------------------------- Object.defineProperty(o,'b',{ get: function(){ return 2; } }) console.log(o.b);//2 //因爲沒有設置set方法,因此o.a=3的賦值語句會靜默失敗 o.b = 1; console.log(o.b);//2
只有set
var o = {} Object.defineProperty(o,'a',{ set: function(){ return 0; } }) o.a = 1; console.log(o.a);//undefined
一般狀況下 get 和set是成對出現的, 而且你會發現,這樣作,咱們還須要空間來存儲值。 這也是數據屬性的不一樣之處吧。
var o = {}; Object.defineProperty(o,'a',{ get: function(){ return this._a; }, set :function(val){ this._a = val*2; } }) o.a = 1; console.log(o.a);//2
var o = {a : 0}; // Object {value: 0, writable: true, enumerable: true, configurable: true} console.log(Object.getOwnPropertyDescriptor(o,'a')); // undefined console.log(Object.getOwnPropertyDescriptor(o,'b'));
var o = {}; Object.defineProperty(o,'a',{ value: 0, writable: true, enumerable: true, }); // /{value: 1, writable: true, enumerable: true, configurable: false} 沒有配置因爲沒有配置configurable,因此它的值爲false console.log(Object.getOwnPropertyDescriptor(o,'a'))
var o = { a : 1, } Object.defineProperties(o,{ a:{enumerable:false}, b:{value:2} }) //{value: 1, writable: true, enumerable: false, configurable: true} console.log(Object.getOwnPropertyDescriptor(o,'a')); //{value: 2, writable: false, enumerable: false, configurable: false} console.log(Object.getOwnPropertyDescriptor(o,'b'));
var o = Object.create(Object.property,{ a:{ value: 0, writable: false, enumerable: true, }, b{ value: 1, } }) //{value: 0, writable: false, enumerable: true, configurable: true} console.log(Object.getOwnPropertyDescriptor(obj,'a')); // {value: 1, writable: true, enumerable: true, configurable: true} console.log(Object.getOwnPropertyDescriptor(obj,'b'))
使用for-in將對象的全部屬性複製到新建的空對象中,並將器返回
function simpleClone(o,cloneObj){ // 判斷參數 for(var i in obj){ cloneObj[i] = obj[i]; } return cloneObj; }
使用屬性描述符
function simpleClone(o){ // 判斷參數 var cloneObj = Object.create(Object.getPrototypeOf(o)); // 根據o對象的原型對象,建立新對象。 // 獲取自身屬性並迭代。 Object.getOwnPropertyNames(o).forEach(function(propKey){ // 根據自身屬性名 獲取屬相描述。 var desc = Object.getOwnPropertyDescriptor(o,propKey); // 給克隆對象設置 屬性描述 Object.defineProperty(cloneObj,propKey,desc); }); return cloneObj; }
複製對象的屬性時,對其進行判斷,若是是數組或對象,則再次調用拷貝函數;不然,直接複製對象屬性
function deepClone(o,cloneObj){ if(typeof o != 'object'){ return false; } var cloneObj = cloneObj || {}; // 保證cloneObj不是null和undefined for(var i in o){ if(typeof o[i] === 'object'){ // 是對象繼續遞歸拷貝 cloneObj[i] = (o[i] instanceof Array) ? [] : {}; arguments.callee(o[i],cloneObj[i]); }else{ cloneObj[i] = o[i]; } } }
使用 json.
先是對象轉成字符串,而後在轉成對象返回。
function jsonDeepClone(o){ return JSON.parse(JSON.string(o)) }