1. 和很多语言一样,在Javascript中可以在对象的后面用“.”运算符来读写属性。
2. Javascript还支持用[] 来读写属性。
var person = {};
person["name"] = "harry";
person["age"] = 32;
for (var property in person) {
console.log(property, ": ", person[property]);
}
上面的代码先在对象person中添加两个分别叫name和age的属性,接着在for...in循环中读取这两个属性的值。
提供[]这种机制获取属性的好处,就是动态指定需要获取的某个属性。比如,我们有如下的一个数组:
var persons = [{
name: "Harry",
age: 32
}, {
name: "Tony",
age: 29
}, {
name: "Andy",
age: 30
}];
当我们对这个数组排序的时候,我们可能是根据name属性进行排序,也可能是根据age属性排序。因此,比较函数需要能够动态指定比较的属性。下面的比较函数满足这个要求:
function getCompareFunction(property) {
return function (object1, object2) {
var value1 = object1[property],
value2 = object2[property];
if (value1 < value2) {
return -1;
}
if (value1 > value2) {
return 1;
}
return 0;
}
}
接下来我们就可以动态指定属性来对数组persons进行排序。
persons.sort(getCompareFunction("name"));
persons.sort(getCompareFunction("age"));
上面代码中,第一行根据name属性排序,而第二行代码根据age属性排序。
3. 在缺省的情况下,对象的属性是可读可写的,甚至我们还可以用delete关键字删除属性。
var person = {
name: "Harry",
age: 32
};
delete person.age;
console.log(person.age);
在上面的代码中由于age属性已经用delete关键字删除了,因此输出为undefined.
4. 如果我们希望修改一个属性是否可写、可删除等特性,我们需要用函数Object.defineProperty来定义或修改属性的特性。
4.1 如果一个属性是数据属性(直接读写某个数据),那么该属性有configurable(属性能否被删除,能否修改特性)、enumerable(属性是否在for...in循环中被遍历到)、writable(属性是否可写)、value(属性对应的数据值)。例如,我们用如下代码定义对象person的属性:
var person = {};
Object.defineProperty(person, "name", {
enumerable: true,
configurable: false,
value: "Harry"
});
Object.defineProperty(person, "gender", {
enumerable: false,
writable: false,
value: "male"
});
如果我们试图用如下代码删除属性name,将会发现name属性仍然存在并且值还是Harry:
delete person.name;
console.log(person.name);
如果我们用如下代码遍历对象person的所有属性:
for (var property in person) {
console.log(property, ": ", person[property]);
}
输出将只有一行name: Harry。这是因为name属性的enumerable特性是true,而gender的enumerable特性是false。
由于gender属性的writable属性是false,该属性的值是不能被修改的。所以下面的代码的输出仍然是male:
person.gender = "female";
console.log(person.gender);
4.2 一个属性还有可能并是直接对应一个数据,而是根据一个或多个数据间接得到的。例如一个商品的实际销售价格可以由基础价格和折扣两个数值得到。下面这段代码应该表达这种价格属性:
var desk = {
_basePrice: 100,
_discount: 0
};
Object.defineProperty(desk, "discount", {
get: function() {
return this._discount;
},
set: function (newDiscount) {
if (newDiscount > 0 && newDiscount <= 1.0) {
this._discount = newDiscount;
} else {
console.error("the value newDiscount should be between 0 and 1");
}
}
});
Object.defineProperty(desk, "price", {
get: function () {
return this._basePrice * (1 - this.discount);
}
});
一个desk对象有两个数值属性_basePrice(基础价格)和_discount(折扣)。在这两个数值属性的基础上,我们定义两个新的属性discount和price(当前的实际价格)。我们为discount属性定义了get和set两个特性函数,表示这个属性既可读又可写。当我们试图读取discount的值的时候,我们实际上得到的是_discount的值。当我们试图更新discount的值的时候,先我们先判断新的值是否在一定的范围内(0到1之间)。如果是,就更新_discount的值;否则输出一行错误信息。同时,我们还定义了price属性,它是根据基础价格和折扣算出来的实际销售价格。由于我们只为price属性定义了set的特性函数,该属性是只可读不可写的。
和数值属性类似,discount和price这样的属性也有configurable和enumerable两个特性。