存取器(accessor)
除了直接定义以外,属性还可以用存取器(accessor)定义。其中,存值函数称为setter,使用set命令;取值函数称为getter,使用get命令
存取器提供的是虚拟属性,即该属性的值不是实际存在的,而是每次读取时计算生成的。利用这个功能,可以实现许多高级特性,比如每个属性禁止赋值。
var o = {
get p() {
return 'getter';
},
set p(value) {
console.log('setter: ' + value);
}
};
上面代码中,o对象内部的get和set命令,分别定义了p属性的取值函数和存值函数。定义了这两个函数之后,对p属性取值时,取值函数会自动调用;对p属性赋值时,存值函数会自动调用。
o.p // "getter"
o.p = 123 // "setter: 123"
注意,取值函数Getter不能接受参数,存值函数Setter只能接受一个参数(即属性的值)。另外,对象也不能有与取值函数同名的属性。比如,上面的对象o设置了取值函数p以后,就不能再另外定义一个p属性。
存取器往往用于,属性的值需要依赖对象内部数据的场合。
var o ={
$n : 5,
get next() { return this.$n++ },
set next(n) {
if (n >= this.$n) this.$n = n;
else throw '新的值必须大于当前值';
}
};
o.next // 5
o.next = 10;
o.next // 10
上面代码中,next属性的存值函数和取值函数,都依赖于对内部属性$n的操作。
存取器也可以通过Object.defineProperty定义。
var d = new Date();
Object.defineProperty(d, 'month', {
get: function () {
return d.getMonth();
},
set: function (v) {
d.setMonth(v);
}
});
上面代码为Date的实例对象d,定义了一个可读写的month属性。
存取器也可以使用Object.create方法定义。
var o = Object.create(Object.prototype, {
foo: {
get: function () {
return 'getter';
},
set: function (value) {
console.log('setter: '+value);
}
}
});
如果使用上面这种写法,属性foo必须定义一个属性描述对象。该对象的get和set属性,分别是foo的取值函数和存值函数。
利用存取器,可以实现数据对象与DOM对象的双向绑定。
Object.defineProperty(user, 'name', {
get: function () {
return document.getElementById('foo').value;
},
set: function (newValue) {
document.getElementById('foo').value = newValue;
},
configurable: true
});
上面代码使用存取函数,将DOM对象foo与数据对象user的name属性,实现了绑定。两者之中只要有一个对象发生变化,就能在另一个对象上实时反映出来。
网友评论