1. 数据属性
# 1. 数据属性
# [[Configurable]]
表示属性是否可以通过delete删除并重新定义,是否可以修改它的特性,是否可以把它改为访问器属性
# [[Enumberable]]
表示属性是否可以通过for-in循环返回
# [[Writable]]
表示能否修改属性的值
# [[Value]]
包含属性实际的值。读取属性值的时候,从这个位置读;写入属性值的时候,把新值保存在这个位置
默认值为undefined
# 1.1 在对象上定义
let person = {
name: "YK菌"
直接在对象上定义的属性,它们的[[Configurable]]、[[Enumerable]]和[[Writable]]特性都被设置为true,而[[Value]]特性被设置为指定的值
# 1.2 使用Object.defineProperty()方法设置属性默认特性
let person = {};
Object.defineProperty(person, "name", {
writable: false,
value: "Nicholas"
});
console.log(person.name); // "Nicholas"
person.name = "Greg";
console.log(person.name); // "Nicholas"
let person = {};
Object.defineProperty(person, "name", {
configurable: false,
value: "Nicholas"
});
// 抛出错误
Object.defineProperty(person, "name", {
configurable: true,
value: "Nicholas"
});
在调用Object.defineProperty()时,configurable、enumerable 和writable 的值如果不指定,则都默认为false
# 2. 访问器属性
访问器属性不包含数据值。相反,它包含一个获取getter函数和一个设置setter函数
# [[Configurable]]
表示属性是否可以通过delete删除并重新定义,是否可以修改它的特性,是否可以把它改为访问器属性
直接在对象上定义的属性,默认值为true
# [[Enumberable]]
表示属性是否可以通过for-in循环返回
直接在对象上定义的属性,默认值为true
# [[Get]]
在读取属性时调用的函数
默认值为undefined
# [[Set]]
在写入属性时调用的函数
默认值为undefined
- 访问器属性不能直接定义,必须使用Object.defineProperty()方法
# 2.1 定义私有成员,设置get、set方法
// 定义一个对象,包含伪私有成员year_和公共成员edition
let book = {
year_: 2017,
edition: 1
};
Object.defineProperty(book, "year", {
get() {
return this.year_;
},
set(newValue) {
if (newValue > 2017) {
this.year_ = newValue;
this.edition += newValue - 2017;
}
}
});
book.year = 2018;
console.log(book.edition); // 2
- year_中的下划线常用来表示该属性并不希望在对象方法的外部被访问。
- 另一个属性year 被定义为一个访问器属性,其中获取函数返回year_的值,而设置函数会做一些计算以决定正确的版本(edition)。
- 这是访问器属性的典型使用场景,即设置一个属性值会导致一些其他变化发生。
- 获取函数和设置函数不一定都要定义。只定义获取函数意味着属性是只读的,尝试修改属性会被忽略。
- 类似地,只有一个设置函数的属性是不能读取的。
# 3. 设置多个属性 Object.defineProperties()
在book 对象上定义了两个数据属性year_和edition,还有一个访问器属性year
let book = {};
Object.defineProperties(book, {
year_: {
value: 2017
},
edition: {
value: 1
},
year: {
get() {
return this.year_;
},
set(newValue) {
if (newValue > 2017) {
this.year_ = newValue;
this.edition += newValue - 2017;
}
}
}
});
# 4. 读取属性的特性Object.getOwnPropertyDescriptor()
- 使用ECMAScript 5的Object.getOwnPropertyDescriptor()方法,可以取得给定属性的描述符。
- 这个方法接收两个参数:属性所在的对象和要读取其描述符的属性名称
- 返回值是一个对象,对于访问器属性包含configurable、enumerable、get 和set 属性,对于数据属性包含configurable、enumerable、writable 和value 属性
let book = {};
Object.defineProperties(book, {
year_: {
value: 2017
},
edition: {
value: 1
},
year: {
get: function() {
return this.year_;
},
set: function(newValue){
if (newValue > 2017) {
this.year_ = newValue;
this.edition += newValue - 2017;
}
}
}
});
let descriptor = Object.getOwnPropertyDescriptor(book, "year_");
console.log(descriptor.value); // 2017
console.log(descriptor.configurable); // false
console.log(typeof descriptor.get); // "undefined"
let descriptor = Object.getOwnPropertyDescriptor(book, "year");
console.log(descriptor.value); // undefined
console.log(descriptor.enumerable); // false
console.log(typeof descriptor.get); // "function"
- ECMAScript 2017 新增了Object.getOwnPropertyDescriptors()静态方法
let book = {};
Object.defineProperties(book, {
year_: {
value: 2017
},
edition: {
value: 1
},
year: {
get: function() {
return this.year_;
},
set: function(newValue){
if (newValue > 2017) {
this.year_ = newValue;
this.edition += newValue - 2017;
}
}
}
});
console.log(Object.getOwnPropertyDescriptors(book));
// {
// edition: {
// configurable: false,
// enumerable: false,
// value: 1,
// writable: false
// },
// year: {
// configurable: false,
// enumerable: false,
// get: f(),
// set: f(newValue),
// },
// year_: {
// configurable: false,
// enumerable: false,
// value: 2017,
// writable: false
// }
// }