不一样的JavaScript(2)——属性

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两个特性。


 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值