前言javascript
我先先看一下javascript權威指南中對 object
的定義:java
對象是一種複合值:他將不少值(原始值或者其餘對象)聚合在一塊兒,能夠經過名字訪問這些值。對象也能夠看作是屬性的無序集合,每一個屬性都是一個鍵/值對(key/value
)。 咱們看到的大多數引用類型值都是 Object
類型的實例;並且,Object
也是 ECMAScript
中使用最多的一個類型。對象其實就是一組數據和功能的集合。json
在 JavaScript
中一共有六種主要類型:數組
• string
• number
• boolean
• null
• undefined
• object
複製代碼
其中基本數據類型有五種:Undefined
、Null
、Boolean
、Number
和 String
。還有 一種複雜數據類型,也就是對象-----Object
。函數
null其實表示一個空對象的指針。這也是使用 typeof 操做符檢測 null 值時會返回"object"的緣由 ui
console.log(typeof null); //object
複製代碼
實際上,JavaScript
中還有許多特殊的對象子類型,能夠稱之爲複雜基本類型。this
此外,JavaScript
中還有一些對象子類型,一般被稱爲內置對象。有些內置對象的名字看起來和簡單基礎類型同樣,不過實際上它們的關係更復雜:spa
• String
• Number
• Boolean
• Object
• Function
• Array
• Date
• RegExp
• Error
複製代碼
內置對象將在下篇文章繼續討論。prototype
建立一個名爲person
的對象:設計
let person = {
name : "小黃瓜",
age : 22
};
複製代碼
在使用對象字面量語法時,屬性名也可使用字符串:
let person = {
"name" : "小黃瓜",
"age" : 22,
};
複製代碼
這裏的數值屬性名會自動轉換爲字符串。
使用對象字面量語法時,若是留空花括號,則能夠定義只包含默認屬性和方法的對象:
let person = {}; ////與 new Object()相同
person.name = "小黃瓜";
person.age = 22;
複製代碼
new
操做符建立並初始化一個新對象,操做符new
後面跟一個構造函數Object
。
let person = new Object();
person.name = "小黃瓜";
person.age = 22;
複製代碼
let person = Object.create({name : '小黃瓜'});
person.name //小黃瓜
複製代碼
Object.create()
其實是建立了一個空對象,並將原型指針指向了傳入的第一個參數。
Object.create = function(new){
let NewObject = {};
NewObject.prototype = new;
return new NewObject();
}
複製代碼
let person = {
name : '小黃瓜',
age : 22
}
//查詢值
console.log(person.name); //小黃瓜
//設置值
person.name = 'guanguan';
console.log(person.name); //guanguan
複製代碼
let person = {
name : 'xiaohuanggua',
age : 22
}
//查詢值
console.log(person["name"]); //xiaohuanggua
//設置值
person["name"] = 'guanguan';
console.log(person["name"]); //guanguan
//但方括號語法的主要優勢是能夠經過變量來訪問屬性
let newName = "name";
console.log(person[newName]); //guanguan
複製代碼
返回一個數組中包含全部屬性名(全部的
key
值)。
let person = {
name : 'xiaohuanggua',
age : 22
}
Object.keys(person); //["name", "age"]
複製代碼
返回一個數組中包含全部屬性值(全部的
value
值)。
let person = {
name : 'xiaohuanggua',
age : 22
}
Object.values(person); //["xiaohuanggua", 22]
複製代碼
delete
運算符
能夠刪除對象的屬性。
let person = {
name : 'xiaohuanggua',
age : 22
}
delete person.name;
console.log(person); //{age: 22}
複製代碼
delete
運算符只能刪除自有屬性,不能夠刪除繼承屬性(要刪除繼承屬性必須從這個屬性的原型對象上刪除)。
delete
運算符不能刪除可配置項爲false
的屬性。
用於檢測對象成員中的所屬關係,判斷某個屬性是否存在於某個對象中。
in
運算符若是右側對象的自有屬性或者繼承屬性中包含左側屬性(字符串),則返回true
,不然返回false
。
let person = {
name : 'xiaohuanggua',
age : 22
}
let test ="name" in person;
console.log(test); //true
let test2 ="sex" in person;
console.log(test); //false
複製代碼
用於判斷屬性是否爲對象的自有屬性,自有屬性返回true
,繼承屬性返回false
。
let person = {
name : 'xiaohuanggua',
age : 22
};
person.hasOwnProperty('name'); //true person對象存在name屬性
person.hasOwnProperty("sex"); //false person對象並無這個屬性
person.hasOwnProperty("toString"); //false 這個屬性是繼承自Object對象
複製代碼
只有當屬性是對象的自有屬性,且屬性的可枚舉性爲
true
是才爲true
,不然爲false
。
let person = {
name : 'xiaohuanggua',
age : 22
};
person.propertyIsEnumerable('name');
//true person對象存在name屬性且可枚舉
person.propertyIsEnumerable('sex');
//false person對象不存在sex屬性
person.propertyIsEnumerable('toString');
//false person對象存在toString屬性,可是toString不是person的自有屬性,且不可枚舉
複製代碼
判斷屬性是否爲
undefined
let person = {
name : 'xiaohuanggua',
age : 22
};
person.name !== undefined; //true
person.sex !== undefined; //false
person.toString !== undefined; //true
複製代碼
可是 !==
操做符 不能區分不存在的屬性和存在可是值爲undefined
的屬性,而in
能夠很好地區分。
let person = {
name : undefined,
};
// !==
person.name !== undefined; //false 屬性存在,但值爲undefined
person.age !== undefined; //false 屬性不存在
// in
'name' in person; //true 屬性存在,但值爲undefined
'age' in person; //false 屬性不存在
複製代碼
let person = {
name : "xiaohuanggua",
age : 22,
sex : 'boy',
};
for(item in person){
console.log(item); //name,age,sex
}
複製代碼
for in老是獲得對象的key值。
得到對象全部可見屬性的屬性名(key值),不包括原型中定義屬性。
let person = {
name : "xiaohuanggua",
age : 22,
sex : 'boy',
};
Object.keys(person); //["name", "age", "sex"]
複製代碼
得到對象全部屬性,不包括原型中定義屬性。
let person = {
name : "xiaohuanggua",
age : 22,
sex : 'boy',
};
Object.getOwnPropertyNames(person); //["name", "age", "sex"]
複製代碼
Get
:在讀取屬性時調用的函數。默認值爲 undefined
。
Set
:在寫入屬性時調用的函數。默認值爲 undefined
。
let man = {
name:'小黃瓜',
weibo:'@xiaohuanggua',
get age(){
return new Date().getFullYear()-1997;
},
set age(val){
console.log('我今年'+ val);
}
}
console.log(man.age); //22 讀取的時候調用
man.age = 1000; //我今年1000 設置的時候調用
複製代碼
數據屬性和訪問器屬性。
數據屬性包含一個數據值的位置,在這個位置能夠讀取和寫入值。
數據屬性特性:
Configurable
:表示可否修改屬性的特性,可否經過 delete
刪除屬性從新從新定義屬性,或者可否把屬性修改成訪問器屬性,這個特性默認值爲 true
。
Enumerable
:表示可否經過循環返回屬性(可枚舉),這個特性默認值爲 true
。
Writable
:表示是否能夠修改屬性的值。默認值爲 true
。
Value
:包含這個屬性的數據值。讀取屬性值的時候,從這個位置讀;寫入屬性值的時候, 把新值保存在這個位置。這個特性的默認值爲 undefined
。
let person = {
name: "小黃瓜" ;
};
複製代碼
直接在對象上定義的屬性,它們的Configurable
、Enumerable
和Writable
都被設置爲 true
,而value
特性被設置爲指定的值。
上面的例子建立了一個名爲 name
的屬性,爲它指定的值是"小黃瓜
"。也就是說,value
特性將 被設置爲"小黃瓜
",而對這個值的任何修改都將反映在這個地方。
而若是要修改屬性默認的特性,必須使用 Object.defineProperty()
方法。
這個方法接收三個參數: 屬性所在的對象、屬性的名字和一個對象。
其中,對象的屬性必須是:configurable
、enumerable
、writable
和 value
。
let person = {};
Object.defineProperty(person, "name", {
writable: false,
value: "小黃瓜"
});
alert(person.name); //"小黃瓜"
person.name = "小綠瓜";
alert(person.name); //"小黃瓜"
複製代碼
咱們建立了一個名爲 name
的屬性,它的值"小黃瓜
"是隻讀的。這個屬性的值是不可修改 的,若是嘗試爲它指定新值,那麼賦值操做無效。
let person = {};
Object.defineProperty(person, "name", {
configurable: false,
value: "小黃瓜"
});
alert(person.name); //"小黃瓜"
delete person.name;
alert(person.name); //"小黃瓜"
複製代碼
由於咱們將 configurable
設置爲 false
,表示不能從對象中刪除屬性,因此刪除操做無效。
一旦把屬性定義爲不可配置的,就不能再把它變回可配置了。那麼再調用Object.defineProperty()
方法修改除 writable
以外的特性,都會致使錯誤:
let person = {};
Object.defineProperty(person, "name", {
configurable: false,
value: "小黃瓜"
});
//報錯!!
Object.defineProperty(person, "name", {
configurable: true,
value: "小黃瓜"
});
複製代碼
訪問器屬性 getter
和 setter
函數(這兩個函數都不是必需的)。 在讀取訪問器屬性時,會調用 getter
函數,這個函數負責返回有效的值;在寫入訪問器屬性時,會調用 setter
函數並傳入新值,這個函數負責如何處理數據。
有以下 四 個特性:
Configurable
:表示可否經過 delete
刪除屬性從而從新定義屬性,可否修改屬性的特 性,直接在對象上定義的屬性,這個特性的默認值爲true
。Enumerable
:表示可否經過循環返回屬性。對於直接在對象上定義的屬性,這個特性的默認值爲 true
。Get
:在讀取屬性時調用的函數。默認值爲 undefined
。Set
:在寫入屬性時調用的函數。默認值爲 undefined
。let person = {
name: '小黃瓜',
edition: 1
};
Object.defineProperty(person, "year", {
get: function(){
return this.name;
},
set: function(newValue){
if (newValue > 2019) {
this.edition = 2;
}
}
});
person.year = 2020;
alert(person.edition); //2
複製代碼
不必定非要同時指定 getter
和 setter
。只指定 getter
意味着屬性是不可寫,寫入屬性會被忽略。
Object.defineProperties()
方法。利用這個方法能夠一次定義多個屬性。
這個方法接收兩個對象參數:第一個對象是要添加和修改其屬性的對象,第二個對象的屬性與第一個對象中要添加或修改的屬性一一對應。
例如:
let person = {};
Object.defineProperties(person, {
name: {
value: '小黃瓜'
},
edition: {
value: 1
},
year: {
get: function(){
return this.name;
},
set: function(newValue){
if (newValue > 2004) {
this.edition = 1;
}
}
}
});
複製代碼
在 person
對象上定義了兩個數據屬性(name
和 edition
)和一個訪問器屬性(year
)。 最終的對象與以前中定義的對象相同。惟一的區別是這裏的屬性都是在同一時間建立的。
Object.getOwnPropertyDescriptor()
方法,能夠取得給定屬性的描述。
這個方法接收兩個參數:屬性所在的對象和要讀取其描述符的屬性名稱。返回值是一個對象,若是 是訪問器屬性,這個對象的屬性有 configurable
、enumerable
、get
和 set
;若是是數據屬性,這個對象的屬性有 configurable
、enumerable
、writable
和 value
。
let person = {};
Object.defineProperties(person, {
name: {
value: '小黃瓜'
},
edition: {
value: 1
},
year: {
get: function(){
return this.name;
},
set: function(newValue){
if (newValue > 2004) {
this.edition = 1;
}
}
}
});
let descriptor = Object.getOwnPropertyDescriptor(person, "name");
alert(descriptor.value); //小黃瓜
alert(descriptor.configurable); //false
alert(typeof descriptor.get); //"undefined"
let descriptor = Object.getOwnPropertyDescriptor(person, "year");
alert(descriptor.value); //undefined
alert(descriptor.enumerable); //false
alert(typeof descriptor.get); //"function"
複製代碼
對象有兩個方法:stringify()
和 parse()
。這兩個方法分別用於把 JavaScript
對象序列化爲 JSON
字符串和把 JSON
字符串解析爲原生 JavaScript
值。
//對象轉字符串
let obj = {x:1,y:true,z:[1,2,3],nullVal:null};
JSON.stringify(obj); //"{"x":1,"y":true,"z":[1,2,3],"nullVal":null}"
//若是存在undefined,則不會出現序列化中
let obj = {val:undefined,a:NaN,b:Infinity,c:new Date()};
JSON.stringify(obj); //"{'a':null,'b':null,'c':2019-06-20T10:32:34}"
//字符串轉對象
let obj = JSON.parse('{"x":1}');
obj.x; //1
複製代碼
每個對象都有與之相關的原型(proto
)、類(class
)、可擴展性(extensible
)。這就是對象的三個屬性。
原型屬性
經過對象字面量的方式建立的對象使用Object.prototype
做爲它們的原型;
經過new
建立的對象使用構造函數的prototype
屬性來做爲它們的原型;
經過Object.create()
來建立的對象使用第一個參數做爲它們的原型。
//想要檢測一個對象是不是另外一個對象的原型(或者處於原型鏈中),使用isPrototypeOf()方法。
let person = {x:1,y:2};
let newPerson = Object.create(person);
person.isPrototypeOf(newPerson);//true
Object.prototype.isPrototypeOf(newPerson);//true
複製代碼
類屬性
用於表示信息對象類型。 只能經過toString()
這種方法查詢對象的類信息。該方法返回以下格式的字符串: [object class]
。接着提取字符串的第八個到倒數第二個位置之間的字符獲得類信息。
經過內置構造函數建立的對象,其類屬性與構造函數的名稱相匹配。
經過對象字面量和Object.create
建立的對象的類屬性是 Object
。
自定義構造函數建立的對象的類屬性也是Object
。
可擴展屬性
用以表示是否能夠向對象添加新屬性。
(詳情見屬性類型)
toString()
方法可用於將當前對象轉換爲字符串形式,並返回結果。
//Object
let person = {name:'小黃瓜',age:1000};
console.log(person.toString()); //[object Object]
//Array
let array = ["小黃瓜", true, 12, -5];
console.log(array.toString()); //小黃瓜,true,12,-5
複製代碼
toLocaleString()
方法返回一個表示這個對象的本地化字符串。可根據本地時間把 Date
對象轉換爲字符串,並返回結果。
let date = new Date();
console.log(date.toLocaleString()); //2019/8/11 下午11:51:09
複製代碼
valueOf()
方法用於返回指定對象的原始值。
// Array:返回數組對象自己
let array = ["小黃瓜", true, 12, -5];
console.log(array.valueOf()); //["小黃瓜", true, 12, -5]
console.log(array.valueOf() === array ); // true
// Object:返回對象自己
let person = {name: "小黃瓜", age: 18};
console.log(person.valueOf()); //{name: "小黃瓜", age: 18}
console.log(person.valueOf() === person ); // true
複製代碼
toJSON()
方法返回其自身的 JSON
數據格式。
//原生 Date 對象 toJSON()方法
let d=new Date();
let n=d.toJSON();
console.log(n); //2019-08-11T16:19:52.681Z
//任何對象添加 toJSON()方法
let book = {
"title": "Professional JavaScript",
"authors": [
"Nicholas C. Zakas"
],
edition: 3,
year: 2011,
toJSON: function(){
return this.title;
}
};
let jsonText = JSON.stringify(book);
console.log(jsonText); //"Professional JavaScript"
複製代碼
toJSON()
能夠做爲函數過濾器的補充。假設把一個對象傳入JSON.stringify()
,序列化該對象的順序以下:
1. 若是存在 toJSON()方法並且能經過它取得有效的值,則調用該方法。不然,返回對象自己。
2. 若是提供了第二個參數,應用這個函數過濾器。傳入函數過濾器的值是第一步返回的值。
3. 對第二步返回的每一個值進行相應的序列化。
4. 若是提供了第三個參數,執行相應的格式化。
複製代碼
關於對象的上半部分已經完結,下一篇還會遠嗎.....
本文參考: