hasOwnProperty 和 propertyIsEnumerable 的區別?

PropertyIsEnumerable

判斷給定的屬性是否可以用 for...in 語句進行枚舉。

hasOwnProperty(property)

判斷對象是否有某個特定的屬性。必須用字元串指定該屬性

請問這兩個方法有什麼區別和哪種情況下哪個方法?

指點一二,感激不盡。


hasOwnProperty 是檢測對象在排除原型鏈的情況下是否具有某個屬性。

比如:

var obj = {x: 1}

obj.hasOwnProperty("x") 返回 true

obj.hasOwnProperty("toString") 返回 false,因為儘管具有obj.toString,但是這個toString是從原型鏈上來的。

var obj = {toString: function(){ return "Hello!" }}

obj.hasOwnProperty("toString") 返回 true

PropertyIsEnumerable 是檢測屬性是否可用 for...in 枚舉

為了便利起見,規範確定某些屬性默認是不可枚舉的,比如Object.prototype.toString

所以你 for (key in {}),是不會遍歷到toString的。

所有自定義屬性默認是可枚舉的,所以 for (key in {toString: ...}),是會遍歷到toString的。為了避免你自定義的toString被枚舉,可以用

Object.defineProperty(obj, "toString", {value: ..., enumerable: false})

由於 for ... in 枚舉是包含原型鏈上的屬性的,所以如果你只想遍歷對象本身的屬性,可以:

for (var key in obj) {
if (obj.hasOwnProperty(key) {
...
}
}

[如果只需要考慮支持ES5的瀏覽器,可以用 Object.keys(obj).forEach 來遍歷。]

反過來說,沒有必要在 for ... in 中去檢測 propertyIsEnumerable,因為不可枚舉的屬性是不會 for...in 出來的。

propertyIsEnumerable這個方法其實用到的場合非常少,基本上已經被Object.getOwnPropertyDescriptor取代。唯一區別是,後者只能得到own property是否enumerable,而前者包含了整個原型鏈。


要注意:比如一個對象obj,其原型上有一個屬性名為"name",執行obj.propertyIsEnumerable("name") ,結果為false!


&第6版 P128,6.4檢測屬性

判斷某個屬性是否存在與某個對象中,可以通過in運算符,hasOwnProperty()和propertyIsEnumerable()方法來完成.

in運算符,如果對象的自有屬性或繼承屬性中包含這個屬性,則返回true.

對象的hasOwnProperty()方法用來檢測給定的名字是否是對象的自有屬性.

propertyIsEnumerable()是hasOwnProperty()的增強版,只有檢測到時自有屬性且這個屬性的可枚舉性為true時才能返回true.


我也測試了一遍,沒有啥區別。是不是推斷沒有啥區別,我還曾經以為propertyIsEnumerable 能取得到原型上的呢

var aaa = {
a: 123,
b: 456
}
var BBB = function (){
this.c = 789;
};
BBB.prototype = aaa;
BBB.prototype.d = 0;
var bbb = new BBB();
bbb.e=function(){};
bbb.f="abc";
console.log(bbb);
for (var i in bbb){
console.log("hasOwnProperty "+bbb.hasOwnProperty(i));
if(bbb.hasOwnProperty(i)){
console.log(i);
console.log(bbb[i]);
}
console.log("propertyIsEnumerable "+bbb.propertyIsEnumerable(i));
if(bbb.propertyIsEnumerable(i)){
console.log(i);
console.log(bbb[i]);
}
}

BBB {c: 789, e: function, f: "abc", a: 123, b: 456…}

test.html:19

hasOwnProperty true test.html:21

c test.html:23

789 test.html:24

propertyIsEnumerable true test.html:26

c test.html:28

789 test.html:29

hasOwnProperty true test.html:21

e test.html:23

function (){} test.html:24

propertyIsEnumerable true test.html:26

e test.html:28

function (){} test.html:29

hasOwnProperty true test.html:21

f test.html:23

abc test.html:24

propertyIsEnumerable true test.html:26

f test.html:28

abc test.html:29

hasOwnProperty false test.html:21

propertyIsEnumerable false test.html:26

hasOwnProperty false test.html:21

propertyIsEnumerable false test.html:26

hasOwnProperty false test.html:21

propertyIsEnumerable false


推薦閱讀:

為什麼初期的前端工程師工資都很高?
請問各位在成為前端工程師之前都是什麼專業出身,入行前端花了多久?
es6用於web前端(非node後端)是不是還太早了?
目前在做前端開發 感覺技術太難做了 想轉行不知道從事什麼行業?
如何看待《為什麼我不想成為Web前端程序員》這篇文章?

TAG:前端開發 | JavaScript | 前端工程師 |