JS中的对象类型:var obj = {a:1}
,可以通过变量.属性名
的形式进行取值、赋值,这种方式虽然便捷,但其创建的属性值可以被任意修改,并可以通过for...in
枚举。__Object.defineProperty()__可以定义、修改对象属性的值及其特性。如今流行的数据双向绑定的JS库中广泛使用了该方法。
语法
首先我们来看一下__Object.defineProperty()__的语法,该函数接收三个参数:
Object.defineProperty(obj, prop, descriptor)
参数
参数名 | 类型 | 描述 |
---|---|---|
obj | Object | 要定义或修改的属性所处的对象 |
prop | String | 要定义或修改的属性名 |
descriptor | Object | 针对该属性的描述 |
返回值
传入的对象
属性描述
第三个参数是一个对象,是针对要定义或修改的属性的详细描述,该对象可以由以下属性组成:
属性名 | 作用 | 默认值 |
---|---|---|
configurable | 该属性是否可以被删除以及其特性是否能够再被修改 | false |
enumerable | 该属性是否可以通过for...in枚举出并且列在Object.keys(obj)的结果中 | false |
value | 该属性的值 | undefined |
writable | 该属性是否可以通过“=”来赋值 | false |
get | 存取器getter,传入一个函数,其返回值即是该属性的值 | undefined |
set | 存取器setter,传入一个函数,只接受一个参数,这个参数为该属性的赋值 | undefined |
Configurable & Enumerable
- 如果属性的__configurable__特性一旦被设为false后,将无法再通过__Object.defineProperty()__改变该属性的特性,并且该属性也无法被删除。
- 如果属性的__enumerable__特性为true,那么可以使用
for...in
来枚举出该属性,并且__Object.keys()__方法也列出该属性。
var obj = {};
Object.defineProperty(obj, 'name', {
value: 'John',
configurable: true,
enumerable: true
});
Object.keys(obj); // Array [ "name" ]
Object.defineProperty(obj, 'name', {
enumerable: false,
configurable: false
});
Object.keys(obj); // Array [ ]
Object.defineProperty(obj, 'name', {
enumerable: true
}); // TypeError: can't redefine non-configurable property "name"
delete obj.name; // false
obj.name; // "John"
Value & Writable
属性的__writable__特性为false时,该属性的值无法进行赋值运算(即:无法使用“=”来赋值),但依旧可以通过__Object.defineProperty()__来更改属性值。
var obj = {};
Object.defineProperty(obj, 'name', {
value: 'John',
writable: false,
configurable: true
});
console.log(obj.name); // "John"
obj.name = 'Marry';
console.log(obj.name); // "John"
Object.defineProperty(obj, 'name', {
value: 'Marry'
});
console.log(obj.name); // "Marry"
var obj = {};
obj.name = 'John';
等价于:
var obj = {};
Object.defineProperty(obj, 'name', {
value: 'John',
writable: true,
configurable: true,
enumerable: true
});
Getter && Setter
- get方法会在获取该属性值的时候执行,属性值即为该方法的返回值
- set方法会在对该属性进行赋值运算(即:使用“=”来赋值)时执行
- set和get方法不能与value并存,也就是说定义了存取器之后,无法再通过__Object.defineProperty()__进行赋值。
var Person = function(name) {
var nameValue;
Object.defineProperty(this, 'name', {
set: function(name) {
nameValue = name.substr(0, 1).toUpperCase().concat(name.substring(1));
},
get: function() {
return nameValue;
}
});
this.name = name;
};
var john = new Person('john');
console.log(john.name); // "John"
浏览器支持
- Chrome 5 +
- FireFox 4 +
- IE 9+
- Opera 11.60 +
- Safari 5.1 +