在学访问器属性之前,我们回味一下属性类型。
ECMAScript中有两种属性: 数据属性和访问器属性。
访问器属性
访问器属性不包含属性值;他们包含一对儿getter和setter函数(这两个函数都不是必需的)。
在读取访问器属性时,会调用getter函数,这个函数负责返回有效的值;
在写入访问器属性时,会调用setter函数并传入新值,这个函数负责决定如何处理数据。
访问器属性有以下4个特性:
var book = {
_year: 2018,
edtion: 1
}
Object.defineProperty(book,"year",{
get: function() {
return this._year;
},
set: function(newValue) {
if(newValue > 2018 ) {
this._year = newValue;
this.edition += newValue - 2018;
}
}
})
book.year = 2019;
console.log(book.edtion);
以上代码创建了一个book对象,并给它定义两个默认的属性:_year和edition。_year前面的下划线是一种常用的记号,用于表示只能通过对象方法访问的属性。
而访问器属性year则包含一个getter函数setter函数。getter函数返回_year的值,setter函数通过计算来确定正确的版本。
因此把year属性修改为2019会导致_year的值变为2019,而edtion变为2。这是使用访问器属性的常见方式,即设置一个属性的值会导致其他属性发生变化。
不一定非要同时指定getter函数和setter函数。
在严格模式下,不指定setter函数,会报如下错误:
Uncaught TypeError: Cannot set property year of #
不指定setter函数,忽略不计。
访问器属性有什么作用呢?
如果我们有这么一个场景
天下
var obj = {
name: '张三'
}
var root = document.getElementById('root');
root.innerHTML = obj.name;
这时候我们会发现页面变为‘张三’了。然后我们继续改变obj.name会发生什么情况呢?
obj.name = '李四';
页面会不会发生改变呢,当然不会哦。
除非我们再一次innerHTML,但这样会特别麻烦。
这时就会用到访问器属性。
Object.defineProperty(obj,'name',{
get: function() {
return this.name;
},
set: function(newValue) {
root.innerHTML = newValue;
}
})
obj.name = '小小1';
你会惊奇的发现,不论你在任何时候改变name的值,就会调用setter和getter函数,从而在页面中展示出来。其实在这里也具备了监听的作用。
如果定义多个属性值时,该如何?这时ECMAScript定义了Object.defineProperties(),此方法有两个参数:
var book = {}
Object.defineProperties(book,{
_year: {
value: 2018
},
edition: {
value: 1
},
get: function() {
return this._year;
},
set: function(newValue) {
if(newValue > 2018 ) {
this._year = newValue;
this.edition = newValue - 2018;
}
}
})
book.year = 2019;
console.log(book.edition); //2
读取属性的特性
Object.getOwnPropertyDescriptor(),接受两个参数:
var descriptor = Object.getOwnPropertyDescriptor(book1,'_year');
//为何描述符都是false。
console.log(descriptor.get); //undefined
var descriptor = Object.getOwnPropertyDescriptor(book1,'year');
console.log(typeof descriptor.get); //function
console.log('descriptor.value',descriptor.value); //undefined
//像这种字面量定义的对象 描述符configurable、enumberable、writable都是true。
var book2 = {
year: 123
}
var descriptor = Object.getOwnPropertyDescriptor(book2,'year');
console.log(descriptor); //{value: 123, writable: true, enumerable: true, configurable: true}
var book3 = {}
Object.defineProperty(book3,'year',{
value: 123
});
var descriptor = Object.getOwnPropertyDescriptor(book3,'year');
console.log(descriptor.writable); //false
//下面的方式不能重写year,因为没有写的权限,writable 是false
//Uncaught TypeError: Cannot assign to read only property 'year' of object '#
问题:
1.像这种字面量定义的对象 描述符configurable、enumberable、writable都是true。为何Object.defineProperty()定义的属性的描述符是false?
书中这样写到:在调用Object.defineproperty()方法时,如果不指定,configurable、enumberable、writable特性的默认值都是false。