枚举属性
可枚举属性
在对象属性中,除了检测对象的属性是否存在,常常还会需要遍历对象的属性,通常使用for/in循环来遍历对象中所有可枚举的属性,包括自有属性和继承属性,但是对象继承的内置属性方法不可枚举。
var o = {
x:1,
y:2,
};
o.name = 'xiaoming';
console.log(o.propertyIsEnumerable("toString")); //false(不可枚举)
//for in 循环可以在循环体中遍历对象中所有可枚举的属性
for(a in o) console.log(a); //x y name
在上面的例子中,toString为对象o继承的内置属性方法,为不可枚举属性,不能遍历出来。现在有很多的工具库给object.prototype添加了新的方法或者属性,这些方法和属性可以被所有对象继承并使用,然而在ECMAScript 5标准之前,这些新的方法不能定义为不可枚举的,即可通过for/in循环出来。为了避免这种情况,我们需要过滤掉这些属性和方法。
for(a in o){
if(!o.hasOwnProperty(a)) continue; //跳过继承属性
console.log(a); //x y name
}
for(a in o){
if(typeof o[a] ==='function') continue; //跳过方法
}
对象属性排序
在使用for/in遍历一个对象的属性的时候,属性名出现的顺序是不确定,如果想要确保属性以特定的顺序出现,最好的办法是避免使用for/in语句,而是创建一个数组,在其中以正确的顺序包含属性名。
var i;
var o = {
'middle-name':'枚',
'last-name':'举',
'first-name':'可'
};
var message = ['first-name','middle-name','last-name'];
for(i=0,j=message.length;i<j;i++){
console.log(message[i] + ':' + o[message[i]]);
}
用来枚举属性的对象工具函数
var p = {
name:'limei',
age:23,
height:180,
like:{
food:'水果',
sports:'跑步',
}
};
var o = {
x:1,
y:2,
}
o.name = 'xiaoming';
下面所有的函数都是建立在上面两个对象的基础上实现的:
1,把p中的可枚举属性复制到o中,并返回o,如果两者含有同名属性,则覆盖o中的属性。
function extend(o,p){
for(prop in p){ //遍历p中的属性
o[prop] = p[prop]; //将属性添加到o中
}
return o;
}
var a = extend(o,p);
console.log(a);
2,把p中的可枚举属性复制到o中,并返回o,如果两者含有同名属性,o中的属性不受影响。
function merge(o,p){
for(prop in p){ //遍历p中属性
if(o.hasOwnProperty[prop]) continue; //过滤掉o中已经存在的属性
o[prop] = p[prop]; //将属性添加到o中
}
return o;
}
var a = merge(o,p);
console.log(a);
3,如果o中的属性在p中没有同名属性,则从o中删除这个属性,并返回o。
function restrict(o,p){
for(prop in o){ //遍历o中的所有属性
if(! (prop in p)) delete o[prop]; //如果该属性在p中不存在,则从o中删除
}
return o;
}
var a = restrict(o,p);
console.log(a);
4,如果o中的属性在p中存在同名属性,则从o中删除这个属性,并返回o。
function subtract(o,p){
for(prop in p){ //遍历p中的所有属性
delete o[prop]; //从o中删除(删除一个不存在的属性不会报错)
}
return o;
}
var a = subtract(o,p);
console.log(a);