js中每个对象都有一个属性叫enumerable(可枚举性),这个属性的true/faslse决定对象的该属性是否可枚举(此属性能否被方法访问到)。
一. 怎么判断一个属性是否可枚举?
① 首先,Object、Array、Number等这种js内置的原型属性不可枚举。
②定义了某个属性的enumberable属性为false,则此属性也不可枚举。
③用obj.propertyIsEnumerable(prop)判断,返回true则可枚举,返回false不可枚举,但是通过原型链继承的属性不能通过此方法判断可枚举性。
④for…in循环:只遍历对象自身的和继承的可枚举的属性。
let obj = {};
Object.defineProperties(obj, {
name: {
value: '祖宗',
enumerable: false, //不可枚举
},
age: {
value: 88,
enumerable: true, //可枚举
}
})
for (let key in obj) {
console.log("key:" + key + ',' + 'value:' + obj[key])
}
运行结果:
⑤Object.keys():返回对象自身的所有可枚举的属性的键名。【注意:不会遍历原型链上的属性】
例:
var arr = ['a', 'b', 'c'];
console.log(Object.keys(arr)); // console: ['0', '1', '2']
// array like object
var obj = { 0: 'a', 1: 'b', 2: 'c' };
console.log(Object.keys(obj)); // console: ['0', '1', '2']
⑥JSON.stringify():串行化对象自身的可枚举的属性。
⑦Object.assign(): 只拷贝对象自身的可枚举的属性。
二.如何遍历对象的所有可枚举属性与不可枚举属性?
使用Object.getOwnPropertyNames(obj)
例:
var my_obj = Object.create({}, {
getFoo: {
value: function() { return this.foo; },
enumerable: false //设getFoo为不可枚举
}
});
my_obj.foo = 1;
console.log(Object.getOwnPropertyNames(my_obj).sort()); // ["foo", "getFoo"],getFoo仍被遍历到了
三.for…in 和 for…of 的区别?
for…in 遍历的是数组的索引,使用for…in会遍历数组所有的可枚举属性,包括原型的一些属性和方法,但是遍历顺序有可能不是按照实际数组的内部顺序,顺序可能随机。
for…of 遍历的是数组的元素值,不会遍历数组的原型属性、方法,所以for of适合遍历数组,可以正确响应break、continue和return语句。
例:
for (var index in myArray) {
console.log(myArray[index]);
// 别这样做,因为在某些情况下,可能按照随机顺序遍历数组元素