最近在回家的路上讀了尼古拉斯的新書《JavaScript面向?qū)ο缶?/a>》,發(fā)現(xiàn)自己對(duì)對(duì)象的屬性和方法不是很熟悉,特別是es5新增的部分,特寫此文總結(jié)一下,同時(shí)也與大家共勉。
本文分為兩部分,分別介紹Object和Object.prototype上的一些常用方法。主要參考了MDN,每個(gè)方法都給出了MDN的鏈接。
查看一個(gè)對(duì)象屬性的最好方法,不是去百度,也不是去google,而是用下面的方法(來自《DOM啟蒙》):
Object.getOwnPropertyNames(Object).sort().forEach(function (val) {console.log(val, '\n')});
上面的代碼會(huì)有如下的輸出,我的環(huán)境是Chrome(52.0.2743.82 m),如果你的環(huán)境不同輸出可能不一樣:
如果不支持getOwnPropertyNames
的瀏覽器就用for in
吧,請(qǐng)自行解決。
從上面的輸出中挑選出一些常用方法和屬性,會(huì)得到下面的列表:
注解:⑤的為es5新增的方法,⑥的為es6(es2015)新增的方法。
下面將會(huì)一一介紹上面的方法。
Object.create() 方法創(chuàng)建一個(gè)擁有指定原型和若干個(gè)指定屬性的對(duì)象。
Object.create(proto [, propertiesObject ])
propertiesObject 包涵若干個(gè)屬性的描述符和defineProperties的第二個(gè)參數(shù)一樣。
Object.create(Object.prototype, { a: { value: 1, writable: true, configurable: true } });
創(chuàng)建一個(gè)繼承自O(shè)bject.prototype的對(duì)象,有一個(gè)屬性a,其可寫,可配置,不可枚舉,值為1。
更多詳情。
Object.defineProperty() 方法直接在一個(gè)對(duì)象上定義一個(gè)新屬性,或者修改一個(gè)已經(jīng)存在的屬性, 并返回這個(gè)對(duì)象。
Object.defineProperty(obj, prop, descriptor)
descriptor 可包含4個(gè)屬性,如下:
其中value和writable一組,get和set一組,不可同時(shí)出現(xiàn)。
// 顯式
Object.defineProperty(obj, "key", {
enumerable: false,
configurable: false,
writable: false,
value: "static"
});
上面給obj對(duì)象定義了一個(gè)屬性key,其不可枚舉,不可配置,只讀,值為static。
更多詳情。
Object.defineProperties() 方法在一個(gè)對(duì)象上添加或修改一個(gè)或者多個(gè)自有屬性,并返回該對(duì)象。
Object.defineProperties(obj, props)
更多詳情。
Object.getPrototypeOf() 方法返回指定對(duì)象的原型(也就是該對(duì)象內(nèi)部屬性[[Prototype]]的值)。
Object.getPrototypeOf(object)
可以用來獲取對(duì)象的原型。
Object.getPrototypeOf({}) === Object.prototype
// > true
在es5之前,要達(dá)到上面同樣的方法,只能使用 constructor。
({}).constructor.prototype === Object.prototype
// > true
但對(duì)于自定義的構(gòu)造函數(shù),如果復(fù)寫了prototype,可能導(dǎo)致獲取的constructor不正確,如何解決這個(gè)問題,可以看這篇文章。
更多詳情。
Object.getOwnPropertyDescriptor() 返回指定對(duì)象上一個(gè)自有屬性對(duì)應(yīng)的屬性描述符。(自有屬性指的是直接賦予該對(duì)象的屬性,不需要從原型鏈上進(jìn)行查找的屬性)
Object.getOwnPropertyDescriptor(obj, prop)
可用來獲取或查看對(duì)象屬性的特性。
var obj = {a: 1};
Object.getOwnPropertyDescriptor(obj, 'a');
// > Object {value: 1, writable: true, enumerable: true, configurable: true}
更多詳情。
Object.keys() 方法會(huì)返回一個(gè)由給定對(duì)象的所有可枚舉自身屬性的屬性名組成的數(shù)組,數(shù)組中屬性名的排列順序和使用for-in循環(huán)遍歷該對(duì)象時(shí)返回的順序一致(兩者的主要區(qū)別是 for-in 還會(huì)遍歷出一個(gè)對(duì)象從其原型鏈上繼承到的可枚舉屬性)。
Object.keys(obj)
典型的用法如下:
var obj = {a: 1, b: 2};
console.log(Object.keys(obj));
// > ["a", "b"]
keys可以用來代替原來的for in循環(huán),借助es5新增的數(shù)組方法,可提升代碼可讀性。
Object.keys(obj).forEach(function (val) {console.log(val)});
更多詳情。
Object.getOwnPropertyNames()方法返回一個(gè)由指定對(duì)象的所有自身屬性的屬性名(包括不可枚舉屬性)組成的數(shù)組。
Object.getOwnPropertyNames(obj)
其和Object.keys的區(qū)別就是能夠獲取自身的全部屬性,包括不可枚舉屬性。
Object.preventExtensions() 方法讓一個(gè)對(duì)象變的不可擴(kuò)展,也就是永遠(yuǎn)不能再添加新的屬性。
Object.preventExtensions(obj)
需要注意的是不可擴(kuò)展的對(duì)象的屬性通常仍然可以被刪除。
嘗試給一個(gè)不可擴(kuò)展對(duì)象添加新屬性的操作將會(huì)失敗,在非嚴(yán)格模式下是靜默的,在嚴(yán)格模式下會(huì)拋出TypeError異常。
Object.preventExtensions 只能阻止一個(gè)對(duì)象不能再添加新的自身屬性,仍然可以為該對(duì)象的原型添加屬性。
在 ECMAScript 5 中可擴(kuò)展的對(duì)象可以變得不可擴(kuò)展,但反過來不行。
更多詳情。
Object.isExtensible() 方法判斷一個(gè)對(duì)象是否是可擴(kuò)展的(是否可以在它上面添加新的屬性)。
更多詳情。
Object.seal() 方法可以讓一個(gè)對(duì)象密封,并返回被密封后的對(duì)象。密封對(duì)象是指那些不能添加新的屬性,不能刪除已有屬性,以及不能修改已有屬性的可枚舉性、可配置性、可寫性,但可能可以修改已有屬性的值的對(duì)象。
Object.seal(obj)
密封一個(gè)對(duì)象會(huì)讓這個(gè)對(duì)象變的變?yōu)椴豢蓴U(kuò)展的,且所有已有屬性會(huì)變的不可配置。屬性不可配置的效果就是屬性變的不可刪除,以及一個(gè)數(shù)據(jù)屬性不能被重新定義成為訪問器屬性,或者反之。但屬性的值仍然可以修改。
嘗試刪除一個(gè)密封對(duì)象的屬性或者將某個(gè)密封對(duì)象的屬性從數(shù)據(jù)屬性轉(zhuǎn)換成訪問器屬性,結(jié)果會(huì)靜默失敗或拋出TypeError異常(嚴(yán)格模式)。
更多詳情。
Object.isSealed() 方法判斷一個(gè)對(duì)象是否是密封的(sealed)。
更多詳情。
Object.freeze() 方法可以凍結(jié)一個(gè)對(duì)象。凍結(jié)對(duì)象是指那些不能添加新的屬性,不能修改已有屬性的值,不能刪除已有屬性,以及不能修改已有屬性的可枚舉性、可配置性、可寫性的對(duì)象。也就是說,這個(gè)對(duì)象永遠(yuǎn)是不可變的。該方法返回被凍結(jié)的對(duì)象。
Object.freeze(obj)
凍結(jié)對(duì)象是不可擴(kuò)展的,密封的,同時(shí)期值屬性的writable會(huì)被設(shè)置為false,set也將失效,總之會(huì)變?yōu)椴豢筛?。任何嘗試修改該對(duì)象的操作都會(huì)失敗,可能是靜默失敗,也可能會(huì)拋出異常(嚴(yán)格模式)。
Object.isFrozen() 方法判斷一個(gè)對(duì)象是否被凍結(jié)(frozen)。
更多詳情。
Object.assign() 方法可以把任意多個(gè)的源對(duì)象自身的可枚舉屬性拷貝給目標(biāo)對(duì)象,然后返回目標(biāo)對(duì)象。
Object.assign(target, ...sources)
Object.getOwnPropertySymbols() 方法會(huì)返回一個(gè)數(shù)組,該數(shù)組包含了指定對(duì)象自身的(非繼承的)所有 symbol 屬性鍵。
Object.is() 方法用來判斷兩個(gè)值是否是同一個(gè)值。
Object.is與嚴(yán)格比較運(yùn)算符(===)的行為基本一致,不同之處只有兩個(gè):一是+0不等于-0,二是NaN等于自身。
將一個(gè)指定的對(duì)象的原型設(shè)置為另一個(gè)對(duì)象或者null(既對(duì)象的[[Prototype]]內(nèi)部屬性)。
Object.setPrototypeOf(obj, prototype)
Object.prototype上的方法,都是實(shí)例方法,必須在對(duì)象實(shí)例上調(diào)用。
hasOwnProperty() 方法用來判斷某個(gè)對(duì)象是否含有指定的自身屬性。
obj.hasOwnProperty(prop)
在沒有Object.keys之前,借助hasOwnProperty,可以讓for in 達(dá)到類似的效果,代碼如下:
for(var key in obj) {
if (obj.hasOwnProperty(key)) {
//過濾掉原型上的方法
}
}
更多詳情。
isPrototypeOf() 方法測試一個(gè)對(duì)象是否存在于另一個(gè)對(duì)象的原型鏈上。
prototype.isPrototypeOf(object)
更多詳情。
propertyIsEnumerable() 方法返回一個(gè)布爾值,表明指定的屬性名是否是當(dāng)前對(duì)象可枚舉的自身屬性。
obj.propertyIsEnumerable(prop)
從原型鏈上繼承的屬性,所以該方法會(huì)返回false。
如果對(duì)象沒有指定的屬性,該方法返回 false。
更多詳情。
一個(gè)對(duì)象的__proto__ 屬性和自己的內(nèi)部屬性[[Prototype]]指向一個(gè)相同的值 (通常稱這個(gè)值為原型),原型的值可以是一個(gè)對(duì)象值也可以是null(比如說Object.prototype.__proto__的值就是null).該屬性可能會(huì)引發(fā)一些錯(cuò)誤,因?yàn)橛脩艨赡軙?huì)不知道該屬性的特殊性,而給它賦值,從而改變了這個(gè)對(duì)象的原型。 如果需要訪問一個(gè)對(duì)象的原型,應(yīng)該使用方法Object.getPrototypeOf。 __proto__ 屬性已經(jīng)被添加在了ES6草案 §B.3.1中。
更多詳情。
除了上面介紹的方法,還有一些實(shí)驗(yàn)方法,和不常用的方法,可以在這里找到。
更多建議: