javascript的hasOwnProperty()和propertyIsEnumerable()的区别

hasOwnProperty 是检查对象在排除原型链的情况下是否具有某个属性。

比如:

var obj = {name: 'wilson'};  
obj.hasOwnProperty('name'); //返回 true  
obj.hasOwnProperty('toString'); //返回 false,因为尽管具有obj.toString,但是这个toString属性是从原型链上来的。  

再来看

var obj = {toString: function(){ return 'Hello!' }};  
obj.hasOwnProperty('toString'); //返回 true  

PropertyIsEnumerable 是检测属性是否可用 for...in 枚举。
为了便利起见,javascript规范确定某些属性默认是不可枚举的,比如Object.prototype.toString, 所以你 for (key in {}),是不会遍历到toString的。 所有自定义属性默认是可枚举的,所以 for (key in {toString: ...}),是会遍历到toString的。为了避免你自定义的toString被枚举,可以用:
Object.defineProperty(obj, 'toString', {value: ..., enumerable: false})

例:

function Gadget(name,color){  
    this.name=name;
    this.color=color;
    this.someMethod=function(){return 1;}
}
Gadget.prototype.price=100;  
Gadget.prototype.rating=3;

var newtoy=new Gadget('webcam','black');

for(var i in newtoy){  
    console.log(i+" = " + newtoy[i]);
}

结果:
name = webcam
color = black
someMethod = function (){return 1;}
price = 100
rating = 3

如果接下来再用defineProperty定义name属性的枚举属性为false,如下: Object.defineProperty(newtoy,'name',{value:'webcam',enumerable: false});
然后在进行一次对newtoy的for-in遍历看看:

for(var i in newtoy){  
    console.log(i+" = " + newtoy[i]);
}

结果如下:
color = black
someMethod = function (){return 1;}
price = 100
rating = 3
可见此时name属性已经不可枚举出来了。

由于 for ... in 枚举是包含原型链上的属性的,所以如果你只想遍历对象本身的属性,可以:

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

[如果只需要考虑支持ES5的浏览器,可以用 Object.keys(obj).forEach 来遍历。]

以上知识部分参考自知乎上的回答:

作者:贺师俊
链接:https://www.zhihu.com/question/21907133/answer/19692092
来源:知乎

Wilson

张弛有度、简约不简单