對象是JavaScript的基本數據類型:屬性的無序集合。每一個屬性key: value
和屬性描述符descripter
組成。數組
屬性名key
:字符串或合法的變量標識符;ide
屬性值value
:能夠是任意JavaScript值(number
、string
、boolean
、null
、undefined
和數組、對象).value
能夠是getter
和setter
。函數
屬性描述符descripter
:每一個屬性的三個相關特性writable
、enumerable
、configurable
,其值都是布爾類型,默認都爲true
工具
建立對象有三種方法:對象字面量{a: 1}
,new Constructor()
、Object.create()
測試
var book = { "main title": "JavaScript", //有空格或其餘非標識符、關鍵字,必須使用雙引號 "sub-title": "The Definitive Guide", "for": "all audiences", author: { firstname: "David", lastname: "Flanagan" } }
new
操做符調用構造函數可使用new
操做符調用一個構造器函數Constructor()
建立一個對象。ui
var o = new String(); var d = new Date();
Object.create()
方法原型:每一個JS對象都有一個與之相關聯的原型對象prototype
,對象其原型對象上繼承屬性。(當前對象中的__proto__
屬性是其原型對象的連接)this
全部經過字面量建立的對象的原型都是Object.prototype
,一個字面量對象{}
至關於調用new Object()
。prototype
Object.prototype
的原型是null
,因此null
是原型的出口。rest
Object.create()
是一個靜態函數(不是提供給對象調用的方法),用於建立對象:code
第一個參數:原型對象,建立的新對象以該參數爲原型;
第二個參數:可選,用於對對象屬性的描述
建立一個沒有原型的對象:Object.create(null);
建立一個普通空對象({}
或new Object()
):Object.create(Object.prototype);
每一個對象都有與之相關的3個屬性:原型prototype
、類屬性calss attribute
、可擴展性extensible attribute
每一個JS對象都與另外一個原型對象(prototype
),利用原型能夠實現繼承。
字面量的原型是:Object.prototype
new
操做符建立的對象其原型:構造器函數的原型(prototype
屬性)
Object.create()
建立的對象,其原型:第一個參數
ES5中定義了Object.getPrototypeOf()
函數,來查詢對象的原型
利用new
建立的對象會繼承constructor
屬性,指向建立該對的構造器函數,全部該對象的原型是:obj.constructor.prototype
字面量{}
的constructor
屬性指向Object()
使用isPrototypeOf()
方法查看一個對象是否爲另外一個對象的原型(或處於原型鏈中)
Array.prototype.isPrototypeOf([]); // ==> true
對象的類屬性class attribute
是一個字符串,用來表示對象的信息。ES3與ES5均爲提供設置類屬性的API,只能經過繼承自Object.prototype
的toString()
方法來簡潔查詢。
{}.toString(); // ==> "[object Object]"
經過對返回字符串切片:第8位到倒數第2位便可得到對象的類型。可是許多對象重寫了toString()
方法,須要間接調用Function
的call()
方法
function classof(o) { if(o === null) {return "Null";} if(o === undefined) {return "Undefined"} return Object.prototype.toString.call(o).slice(8, -1); }
classof()
方法能夠返回傳遞給它的任意對象的類型,參數爲number
、string
、boolean
時,使用包裝類型將其轉化爲對象,再進行操做。
classof(null); // ==> "Null" classof(2); // ==> "Number" classof(false); // ==> "Boolean" classof(new Date()); // ==> "Date" classof(""); // ==> "String" classof({}); // ==> "Object" classof([]); // ==> "Array" classof(/./); // ==> "RegExp" classof(window); // ==> "Window",宿主對象 function F() {}; //自定義一個構造器函數 classof(new F()); // ==> "Object"
extensible attribute
對象的課擴展性用來描述對象是否能夠添加新的屬性。全部的內置對象和自定義對象都是可擴展的,除非將其轉化爲不可擴展
Object.esExtensible()
函數判斷傳入對象是否能夠擴展;
Object.preventExensible()
函數將傳入的對象設置爲不可擴展,而且過程不可逆;隻影響對象自己的可擴展性
Object.seal()
函數將對象設置爲不可擴展,屬性描述符configurable
設置爲false
(不能添加新屬性,已有的屬性不能刪除或配置,可是對於writable: true
時,能夠修改屬性的值);過程不可逆
Object.isSealed()
函數判斷一個對象是否封閉
Object.freeze()
函數將對象設置爲不可擴展,屬性描述符configurable: false;
,writable: false;
只讀。value
爲accessor property
含有setter
函數,不受影響
每一個對象是無需的屬性集合,屬性名能夠是合法的變量標識符或字符串;變量值能夠是任意JavaScript值;屬性由描述符descripter
來控制特性;
屬性能夠經過.
和[]
來訪問:
使用.
訪問時,其右側必須是屬性名稱命名的簡單標識符
使用[]
訪問時,括號內必須是計算結果爲字符串的表達式,字符串是屬性的名字。變量名爲關鍵字、含有空格或屬性名是變量時,必須使用[]
var author = book.author; var name = author.surname; var title = book["main title"];
屬性的設置:與訪問類似,將其放在賦值表達式的左側
book.edtion = 6; book["main title"] = "ECMAScript";
在查詢一個對象是否存在時,先查看自身屬性,若是沒有;經過原型鏈逐層向上查找,直到原型鏈頂端null
爲止。
若是自身屬性與原型鏈中均爲找到,屬性訪問返回undefined
,不報錯
若是查詢不存在對象的屬性,會報錯
爲null
和undefined
設置屬性會報錯
使用delete
操做符,能夠刪除對象的屬性(其描述符中configurable
爲true
),而且只能刪除自有屬性,不能刪除繼承屬性
判斷某個屬性是否在某個對象中,JS有三種方法:in
、hasOwnProperty()
、propertyIsEnumerable()
in
:若是對象自身屬性或繼承屬性中包含該屬性,返回true;
hasOwnProperty()
:只有對象自身屬性包含該屬性時,才返回true
propertyIsEnumerable()
:只有對象自身屬性包含該屬性,而且該屬性是能夠枚舉(描述符中enumerable: true;
)
var o = {a : 1}; "a" in o; // ==> true o.hasOwnProperty("a"); // ==> true o.propertyIsEnumerable("a"); // ==> true
使用for-in
循環能夠遍歷對象中全部可枚舉的屬性(包括自身屬性與繼承屬性),把屬性名賦值給循環變量。ES5定義了Object.keys()
和Object.getOwnPropertyNames()
兩個函數用來枚舉屬性名稱。
Object.keys()
:返回對象中可枚舉的自有屬性名組成的數組
Object.getOwnPropertyNames()
:返回對象全部的自有屬性名組成的數組,包括不可枚舉的屬性
對象繼承的內置方法都是不可枚舉的,給對象中增長的屬性均可以枚舉(除非設置其enumerable: false
)
有許多使用工具庫爲Object.prototype
增長新的屬性,這些屬性能夠被全部對象繼承使用,可是在ES5以前,不能將其設置爲不可枚舉,因此在for-in
循環時會被枚舉出來。
//過濾繼承的屬性 for(p in o) { if(!o.hasOwnProperty(p)) {continue;} } //跳過方法 for(p in o) { if(typeof p === "function") {continue;} }
操做對象屬性的工具函數:
/** * 枚舉屬性的工具函數 * 將對象p中可枚舉的屬性複製到對象o中,返回對象o; * 若是p和o含有同名的屬性,則覆蓋o中的屬性 * 不處理getter和setter以及複製屬性 */ function extend(o, p) { for(let prop in p) { o[prop] = p[prop]; } return o; } /** * 將對象p中可枚舉的屬性複製到對象o中,返回對象o; * 若是o和p有同名屬性,不影響o中的屬性 * 不處理getter和setter以及複製屬性 */ function merge(o, p) { for(let prop in p) { if(o.hasOwnProperty(prop)) { continue; } o[prop] = p[prop]; } return o; } /** * 若是o中的屬性在p中沒有同名屬性,從o中刪除這個屬性,並返回o */ function restrict(o, p) { for(let prop in o) { if(!(prop in p)) { delete o[prop]; } } return o; } /** * 若是o中的屬性在p中存在同名屬性,從o中刪除這個屬性,並返回o */ function substrict(o, p) { for(let prop in o) { if(prop in p) { delete o[prop]; } } return o; } /** * 返回一個數組,包含o中可枚舉的自有屬性的名字 */ function keys(o) { //o必須是對象 if(typeof o !== 'object') { throw TypeError(); } var result = []; for(let prop in o) { if(o.hasOwnProperty(prop)) { result.push(prop); } } return result; }
setter
和getter
屬性的組成:key
、value
、descripter
。在ES5中,value
能夠用一個或兩個方法替代(getter
和setter
方法)
全部JavaScript的value
叫作數據屬性data property
getter
和setter
定義的屬性叫作存取器屬性:accessor property
不一樣於data property
,accessor property
的讀寫屬性由getter
和setter
決定。
若是屬性同時有getter
和setter
,它是一個可讀寫的屬性;
若是屬性只有getter
,它是一個只讀的屬性;
若是屬性只有setter
,它是一個只寫的屬性;讀取只寫屬性老是返回undefined
getter
和setter
定義var o = { data_prop: value; //普通數據屬性 //存取器屬性是成對定義的函數,函數名是該屬性名,沒有冒號分隔函數體以屬性名 get accessor_prop() {...}, set accessor_prop(value) {...} }
var p = { //x、y是普通可讀寫的數據屬性 x: 1.0, y: 1.0, //r是可讀寫的存取器屬性,具備getter和setter //函數結束後要帶上逗號 get r() {return Math.sqrt(this.x * this.x + this.y * this.y)}, set r(newvalue) { var oldvalue = Math.sqrt(this.x * this.x + this.y * this.y); var ratio = newvalue / oldvalue; this.x *= ratio; this.y *= ratio; }, //theta是隻讀存取器屬性,只有getter方法 get theta() {return Math.atan2(this.y, this.x)} };
函數體內的this
指向表示這個點的對象
descripter
屬性除key
、value
,還有一組用於描述其特性的descripter
,其中有writable
、enumerable
和configurable
三個屬性,其值都爲布爾類型,默認爲true
假設將setter
和getter
看作descripter
,同理將屬性的value
也看作descripter
data property
的四個特性:value
、writable
、enumerable
、configurable
accessory property
的四個特性:getter
、setter
、enumerable
、configurable
ES5提供操做descripter
的API:
調用Object.getOwnPropertyDescripter()
函數,獲取某個對象中特定自有屬性的descirpter
調用Object.getPrototypeOf()
函數能夠獲取繼承屬性的descirpter
調用Object.defineProperty()
函數能夠設置屬性的特性,或者新建屬性,使其具備某種特性
//返回{ value: 1, writable: true, enumerable: true, configurable: true } Object.getOwnPropertyDescriptor({a: 1}, "a"); //繼承屬性和不存在的屬性,返回undefined Object.getOwnPropertyDescriptor({}); Object.getOwnPropertyDescriptor({}, "toString");
var o = {}; //建立空對象 //添加一個不可枚舉的屬性,其值爲1 Object.defineProperty(o, "x", {value: 1, writable: true, enumerable: false, configurable: true}); o.x; //屬性存在,但不可枚舉, ==>1 Object.keys(o); // ==> [] //對x屬性進行修改,使其變爲只讀 Object.defineProperty(o, 'x', {writable: false}); o.x = 2; //操做失敗,但不報錯;在嚴格模式下拋出類型錯誤 o.x; // ==> 1 //屬性的值能夠配置 Object.defineProperty(o, 'x', {value: 2}); o.x; // ==> 2 //將x從數據屬性修改成存取器屬性 Object.defineProperty(o, 'x', {get function() {return 0;}}); o.x; //==> 0
序列化對象指將對象的狀態轉化爲字符串,同時能夠將JSON
字符串轉化爲對象。ES5內置JSON
對象的JSON.stringgify()
和JSON.parse()
能夠完成序列化和解析。
var o = {x: 1, y: {z: [false, null, ""]}}; //測試對象 var s =JSON.stringify(o); // '{"x":1,"y":{"z":[false,null,""]}}' var p = JSON.parse(s); //p是s的深拷貝
JSON
是JavaScript的子集,不能表示JavaScript中全部值。
能夠表示:object
、Array
、string
、number
、boolean
、null
,能夠序列化與還原。infinity
、NaN
序列化結果是null
,Date
對象序列化結果是日期字符串
不能表示:函數、RegExp
、Error
對象和undefined
JSON.stringify()
只能序列化對象自有的可枚舉屬性。
Object.prototype
對象的方法hasOwnProperty()
:檢測該屬性是否爲對象自有屬性
propertyIsEnumerable()
:檢測該屬性是不是對象自有,而且可枚舉的屬性
isPrototypeOf
:檢測某對象是否爲另外一個對象的原型
toString()
:無參數,返回調用該方法對象值的字符串,因爲功能有限,某些對象重寫了該方法:Array.toString()
、Date.toString()
、Function.toString()
toLoaclString()
:Object
中的toLoaclString()
只是調用toString()
,只有Date
和Number
類對toLoaclString()
定製,能夠對數字、日期和時間進行本地化處理
JS中對象是屬性的無序集合,每一個對象有三個相關特性:原型prototype
、類屬性class property
、可擴展性extensible
對象的建立三種方法:對象字面量、new
調用構造函數和Object.create()
每一個屬性由三個部分組成:key
、value
和descripter
key
只能是字符串或者值爲字符串的變量標識符
value
能夠是任意JavaScript值(數據屬性data property
);能夠是一個或兩個方法,getter
和setter
(控制區屬性accessor property
)
descripter
:writable
、enumerable
、configurable
,其值都是布爾類型,默認都爲true
。可使用Object.defineProperty()
操做描述符特性。
writable
指該屬性是否能夠寫入數據;enumerable
指該屬性是否能夠枚舉,(使用for-in
循環能夠列出,ES5提供Object.keys()
和Object.getOwnPropertyNames()
);configurable
指該屬性是否能夠用delete
操做符刪除和配置。