关于object属性的可枚举性
Object属性主要包含两种:数据属性和访问器属性。
数据属性包含一个数据值的位置,在这个位置可以读取和写入值。包含4个描述行为的特性:
Configurable:表示能否通过delete删除属性从而重新定义属性,能否修改属性的特性,或者能否把属性修改为访问器属性。
Enumerable:表示属性是否可枚举,能否通过for-in循环返回属性。默认值是TRUE
Writable:表示能否修改属性的值。默认值是TRUE
Value:当前属性的数据值。可以读写,默认为undefined
访问器属性不包含数据值,它包含一对getter和setter函数,getter是返回一个有效的值,setter是设置一个新值。同样包含4个描述行为特性:
Configurable和enumerable:与数据属性相同
get:读取值的函数
set:设置新值调用的函数
根据上下文环境的不同,又可以将属性分为:原型属性和实例属性。原型属性是定义在对象的原型(prototype)中的属性,而实例属性一方面来自构造的函数中,然后就是构造函数实例化后添加的新属性。
属性值的操作:
聊属性值的操作之前我们先知悉一下Object实例创建的方法,Object实例创建方法包含两种:
1. 使用new操作符后面跟Object构造函数
2. 使用对象字面量表示法
属性值的操作:
1. obj.xx = xx;
2. obj[‘xx’] = xx;
一般来说,访问对象属性时使用的都是点表示法,这也是很多面向对象语言中通用的语法。不过,
在JavaScript 也可以使用方括号表示法来访问对象的属性。在使用方括号语法时,应该将要访问的属性
以字符串的形式放在方括号中,如下面的例子所示。
alert(person["name"]); //"Nicholas"
alert(person.name); //"Nicholas"
从功能上看,这两种访问对象属性的方法没有任何区别。但方括号语法的主要优点是可以通过变量
来访问属性,例如:
var propertyName = "name";
alert(person[propertyName]); //"Nicholas"
如果属性名中包含会导致语法错误的字符,或者属性名使用的是关键字或保留字,也可以使用方括
号表示法。例如:
person["first name"] = "Nicholas";
由于"first name"中包含一个空格,所以不能使用点表示法来访问它。然而,属性名中是可以包
含非字母非数字的,这时候就可以使用方括号表示法来访问它们。
通常,除非必须使用变量来访问属性,否则我们建议使用点表示法。
关于属性的枚举性
可枚举属性是指那些内部 “可枚举” 标志设置为 true 的属性,对于通过直接的赋值和属性初始化的属性,该标识值默认为即为 true,对于通过Object.defineProperty等定义的属性,该标识值默认为 false。可枚举的属性可以通过for...in循环进行遍历。
遍历对象的属性,我们常用方法是(for in),Object.keys和Object. getOwnPropertyNames(obj)。
那么他们之间有什么差别呢?
For in遍历属性时,包含该实例上的属性和该实例对象上的原型属性,不包含不可枚举的属性
判断是否实例自身属性obj.hasOwnProperty(key)
getOwnPropertyNames(obj),包含该实例上的属性和不可枚举的属性,不包含对象原型上的属性。
判断是否可枚举obj.propertyIsEnumerable(val)
Object.keys只返回实例上的属性,不含不可枚举的和原型上的。
代码演示:
function Cat(){
this.name = 'xiaoxiao';
this.age = 2;
}
Cat.prototype = {
say:function(){
console.log("I am lovely");
},
eat:function(){
console.log("I like fish");
}
}
var cat = new Cat();
cat.play = function(){
console.log("I am playing");
}
cat['sex'] = 'female';
//定义一个数据属性
Object.defineProperty(cat, 'color',{
//属性是否可枚举
enumerable: false,
//是否可删除属性
configurable: true,
//是否能修改属性的值
writable: true,
//属性的值
value:'black'
});
//定义一个访问器属性
Object.defineProperty(cat ,'_age', {
enumerable:true,
configurable:true,
get:function(){
return this.age;
},
set:function(newVal){
if(this.age != newVal)
this.age = newVal;
}
});
for(var key in cat){
console.log(key);//name,age,play,sex,_age,say,eat
}
for(var key in cat){
if(!cat.hasOwnProperty(key)) continue;
console.log(key);// //name,age,play,sex,_age
}
Object.keys(cat);
//["name", "age", "play", "sex", "_age"]
Object.getOwnPropertyNames(cat);
//["name", "age", "play", "sex", "color", "_age"]