ECMA-262 定义对象
对象是一组属性的无序集合。
可配置
- 表示属性
- 是否通过 delete 删除并重新定义,
- 是否可以修改特征
- 是否可以改为访问器属性
- 默认 true (如果被设置为 false,就不能再变回可配置)
- [[Enumerable]]
可枚举
- [[Enumerable]]
- 表示属性是否通过 for-in 循环返回
- 默认 true
- [[Writable]]
可写
- [[Writable]]
- 表示属性的值是否可以被修改
- 默认 true
- [[Value]]
值
- [[Value]]
- 表示属性实际的值
- 默认 undefined
使用显式定义对象,除 [[Value]] 外,其它数据属性都会以其默认值 true。而 [[Value]] 设置为指定的值。
调用
Object.defineProperty()
/Object.defineProperties()
不指定 configurable、enumerable、writable 值,默认为 false。
访问器属性
- [[Configurable]]
可配置
- 表示属性
- 是否通过 delete 删除并重新定义,
- 是否可以修改特征
- 是否可以改为访问器属性
- 默认 true (如果被设置为 false,就不能再变回可配置)
- [[Enumerable]]
可枚举
- [[Enumerable]]
- 表示属性是否通过 for-in 循环返回
- 默认 true
- [[Get]]
getter
- [[Get]]
- 获取函数,读取属性时调用
- 默认 undefined
- [[Set]]
setter
- [[Set]]
- 设置函数,写入属性时调用
- 默认 undefined
getter 取值函数 和 setter 存值函数
设置 getter 会取代 value
设置 setter 会取代 writable
getter 与 setter 最好成对出现,如果单独定义var obj = {
a: 1,
get c(){
console.log('getter:');
return this.a;
},
set c(val){
console.log('setter:', val);
this.a = val * 2;
}
}
- 只定义 getter 函数,静默失败,严格模式会报错 ```javascript var obj = { get a(){ return 2; } }
console.log(obj.a); // 2 obj.a = 10; // 这里会执行,但会静默失败。在严格模式下会报错 console.log(obj.a); // 2
![image.png](https://cdn.nlark.com/yuque/0/2021/png/1753568/1622377742028-5f74d46f-fa4a-4bfb-b55e-696845f0603d.png#clientId=u0166b12d-f5b9-4&from=paste&height=50&id=u685f3155&margin=%5Bobject%20Object%5D&name=image.png&originHeight=50&originWidth=519&originalType=binary&ratio=1&size=39470&status=done&style=none&taskId=u782c37f6-e62b-4c03-83f0-aab82145976&width=519)
2. 只定义 setter 函数,获取属性值为 undefined
2. 所以 getter,setter 一定要成对出现
```javascript
var obj = {
set a(val){
console.log(val); // 10
return 2;
}
}
console.log(obj.a); // undefined
obj.a = 10;
console.log(obj.a); // undefined
访问器属性可以通过 Object.defineProperty()
/ Object.defineProperies()
或者
定义对象属性前使用 get / set 修饰符
var book = { year_:2017, edition: 1 };
Object.defineProperty(book, 'year', {
get: function() {
return this.year_;
},
set: function(newValue){
if (newValue > 2017) {
this.year_ = newValue;
this.edition += newValue - 2017;
}
}
});
// 或者 Object.defineProperties() 多个属性一起定义
var book = {};
Object.defineProperties(book, {
year_: {
value: 2017,
writable: true // Object.defineProperty() / Object.defineProperties()
// 不指定 configurable、enumerable、writable 值,默认为 false
},
edition: {
value: 1,
writable: true // 原理同上,writable 为 false,下面的 year setter 就没有任何效果了
},
year: {
get: function() {
return this.year_;
},
set: function(newValue){
if (newValue > 2017) {
this.year_ = newValue;
this.edition += newValue - 2017;
}
}
}
});
// 或者 在显式定义对象中使用 get / set 修饰符,更加简化
var book = {
year_:2017, edition: 1,
get year(){
return this.year_;
},
set year(newValue){
if (newValue > 2017) {
this.year_ = newValue;
this.edition += newValue - 2017;
}
}
};
IE8 兼容性
IE8 的 Object.definedProperty()
只支持 DOM,但可以使用两个非标准的访问创建访问器属性
- defineGetter()
- defineSetter() ```javascript var book = {year_:2017, edition: 1};
book.defineGetter(‘year’, function(){ return this.year_; });
book.defineSetter(‘year’, function(newValue){ if (newValue > 2017) { this.year_ = newValue; this.edition += newValue - 2017; } });
> 不支持 `Object.defineProperty()` 的浏览器中没有办法修改 [[Configurable]] 或 [[Enumerable]]
<a name="QXatt"></a>
# 对象禁止配置
不允许对象增加属性
```javascript
Object.prototype.isExtensable(obj);
Object.prototype.preventExtensions(obj);
对象封印
不允许对象增加、删除属性
Object.prototype.isSealed(obj);
Object.prototype.seal(obj);
对象冻结
不允许对象增加、更改、删除属性
Object.prototype.isFrozen(obj);
Object.prototype.freeze(obj);