先把總結(jié)寫在這里:
- JavaScript對象的屬性可分為可枚舉和不可枚舉柳骄,它是由屬性的
enumeration
值決定的夹界,true
為可枚舉,false
為不可枚舉 - 原生構(gòu)造函數(shù)(Boolean, Number, String 等)的內(nèi)置屬性(例如 toSring可柿、 constructor等) 和 引擎內(nèi)置對象的屬性(Math 的 random 等) 一般是不可枚舉的,而自己定義的屬性(不管是原型上的還是自身的)一般是可枚舉的复斥。
- 屬性的枚舉性會影響以下四個方法的結(jié)果
1)for...in
2 )Object.keys()
3)JSON.stringify()
4)Object.assign()
小結(jié):
- 這四個方法中,只有
for/in
是對所有可枚舉屬性(對象本身的可枚舉屬性目锭,以及從其構(gòu)造函數(shù)原型中繼承的可枚舉屬性),而其他三種是對自身可枚舉屬性才有效痢虹。 - 而四個方法中又只有
Object.assign()
對 Symbol 屬性有效主儡,其他三種對 Symbol 都會過濾掉。
這里做一個其他的小總結(jié): - 上面四個方法中糜值,其中
Object.assign()
無法正確拷貝get屬性和set屬性,而JSON.stringify()
對對象的方法寂汇、undefined值、get 屬性骄瓣、set屬性無效 。 - 如果該參數(shù)不是對象榕栏,則會先轉(zhuǎn)成對象畔勤,然后返回臼膏。
由于undefined和null無法轉(zhuǎn)成對象,所以如果它們作為(第一個)參數(shù)渗磅,就會報錯检访。有這兩種特性的方法是:
Object.assign() 、 Object.setPrototypeOf()脆贵、Object.getPrototypeOf()
上面說了JavaScript對象的屬性是否可枚舉是 enumeration 的值決定的,那么enumeration是什么時候怎么去設(shè)置的呢卖氨?
enumeration 是 Object.defineProperty() 方法的一個參數(shù),下面來看看怎么去設(shè)置 一個屬性是否可枚舉筒捺。
var person = {
name:'zhou',
age: '12',
sex: 'girl'
}
Object.defineProperty(person,'age',{
enumerable:true,//可以被枚舉
});
Object.defineProperty(person,'sex',{
enumerable:false,//可以被枚舉
})
for(var k in person){
console.log(person[k])//a,可以被枚舉
}
//12
//zhou
如何設(shè)置是否可枚舉-- enumerable
由上面的點可以看出:
1.Object.defineProperty(obj, prop, descriptor)方法有三個參數(shù),每個參數(shù)各代表著
第一個:目標屬性所在的對象系吭,
第二個:目標屬性,放在字符串里颗品,
第三個:目標屬性的行為,放在對象里躯枢;
2.enumerable為true表示可枚舉,enumerable為false表示不可枚舉锄蹂;
3.開發(fā)者自定義的對象person的所有屬性都是可枚舉的;
如何判斷是否可枚舉-- obj.propertyIsEnumerable()
在不知情的情況下败匹,如何判斷一個屬性是否可枚舉呢?obj.propertylsEnumerable()方法可以解決這個問題掀亩。
- 語法:obj.propertyIsEnumerable(prop)
- 定義:每個對象都有一個
propertyIsEnumerable
方法欢顷,表示指定的自身屬性是否可枚舉 (繼承屬性無效) ,返回一個布爾值(當對象沒有該指定屬性時也返回 false)。 - 用法:
1)就上面的例子的使用
person.propertyIsEnumerable('name');//true
person.propertyIsEnumerable('age');//true
person.propertyIsEnumerable('sex');//false
2)引擎內(nèi)置對象的屬性不可枚舉
var o = {};
var a = [];
o.prop = 'is enumerable';
a[0] = 'is enumerable';
o.propertyIsEnumerable('prop') // true
a.propertyIsEnumerable(0); // true
Math.propertyIsEnumerable('random') // false
Object.propertyIsEnumerable('constructor') // false
從 用法1 和 用法2 可以看出用戶自定義屬性是可枚舉的(一般情況下自定義屬性都是可枚舉的抬驴,除非像 person.sex 經(jīng)過屬性描述符的修改),而瀏覽器內(nèi)置對象如 Math 的屬性是不可枚舉的布持。
3)原生構(gòu)造函數(shù)的內(nèi)置屬性不可枚舉,如Boolean, Number, String, Array, Date, Function, RegExp, Error, Object
var num = new Number();
for(var prop in num) {
console.log(prop);
}
輸出為空题暖。for in 訪問的是所有可枚舉屬性捉超,這里輸出為空,說明Number中內(nèi)置的屬性是不可枚舉的唯绍,例如 toString() 方法拼岳。
4)自定義屬性一般為可枚舉屬性( 不管是自身屬性還是原始上的繼承屬性 )
說明:
- 開發(fā)者自定義的屬性在一般情況下是可枚舉的
-
for /in
對所可以訪問到所有可枚舉屬性 -
obj.propertyIsEnumerable(prop)
只能訪問到 對象自身可枚舉屬性(對象自身添加的、構(gòu)造函數(shù)實例化的) 有效惜纸,對原始上的繼承屬性無效。 -
obj.hasOwnProperty(prop)
返回一個布爾值耐版,指示對象自身屬性中是否具有指定的屬性 -
Object.getOwnPropertyNames(obj)
返回一個由指定對象的所有自身屬性的屬性名(包括不可枚舉屬性但不包括Symbol值作為名稱的屬性)組成的數(shù)組。 -
Object.keys()
方法會返回一個由一個給定對象的自身可枚舉屬性組成的數(shù)組粪牲。
//構(gòu)造函數(shù)
function People() {
this.hobby = 'eat';
}
People.prototype.showHooby = function() {};
//繼承
function Coder() {
this.love = function method() { return 'coder‘s love is codeing'; };
}
Coder.prototype = new People;
Coder.prototype.constructor = Coder;
//實例
var c = new Coder();
c.age = '24';
//打印出實例
console.dir(c)
我們來看看打印出來的實例對象蛾魄,看看哪些屬性是自身的,哪些屬性是在原型上的
用 for/in
來訪問 o
對象滴须,看看哪些屬性是可枚舉的:
for(var prop in c){
console.log(prop)
}
// love
// age
// hobby
// constructor
// showHooby
自定義屬性都可枚舉舌狗,不管是自身屬性還是原始上的繼承屬性
怎么過濾出自身可枚舉屬性呢痛侍?就可以用 obj.propertyIsEnumerable()
, Object.getOwnPropertyNames()
, obj.hasOwnProperty
, Object.keys()
方法啦
// obj.propertyIsEnumerable() --- 先找出*所有可枚舉屬性*,再找出自身的可枚舉屬性
for(var prop in c){
if(c.propertyIsEnumerable(prop)) console.log(prop)
}
// love
// age
// 或者 obj.hasOwnProperty() --- 先找出*所有可枚舉屬性*主届,再找出自身屬性
for(var prop in c){
if(c.hasOwnProperty(prop)) console.log(prop)
}
// love
// age
// 或者 Object.getOwnPropertyNames() --- 先找出*所有自身屬性*的屬性名,再找出可枚舉的
var cName = Object.getOwnPropertyNames(c);
for(var prop in cName){
console.log(cName[prop])
}
// love
// age
// 或者 Object.keys() --- 直接找出自身可枚舉屬性
Object.keys(c)
//["love", "age"]
參考鏈接:
MDN:Object
MDN: 屬性的可枚舉性和所有權(quán)
自己總結(jié)了大半天君丁,然后看到阮大神比較全的一篇:
阮一峰:屬性的可枚舉與遍歷
上面說到關(guān)于對象屬性“枚舉性”的多種方法,這里放放上一張這些屬性微妙差別的對比圖: